linux: keep bluetooth classic only

This commit is contained in:
kidfromjupiter
2026-01-05 10:36:36 +05:30
parent e2256ca83d
commit 589e638b13
96 changed files with 394 additions and 9771 deletions
@@ -54,12 +54,6 @@ cc_library(
cc_library(
name = "comm",
hdrs = [
"avahi.h",
"ble_gatt_server.h",
"ble_gatt_client.h",
# "ble_medium.h",
# "ble_v2_medium.h",
# "ble_v2_server_socket.h",
"bluetooth_adapter.h",
"bluetooth_bluez_profile.h",
"bluetooth_classic_device.h",
@@ -71,31 +65,8 @@ cc_library(
"bluez.h",
"bluez_device.h",
"bluez_agent.h",
# "bluez_advertisement_monitor.h",
# "bluez_advertisement_monitor_manager.h",
# "bluez_gatt_characteristic_client.h",
# "bluez_gatt_characteristic_server.h",
# "bluez_gatt_manager.h",
# "bluez_gatt_service_client.h",
# "bluez_gatt_service_server.h",
# "bluez_le_advertisement.h",
"dbus.h",
# "network_manager.h",
# "network_manager_active_connection.h",
# "network_manager_access_point.h",
"stream.h",
# "tcp_server_socket.h",
# "wifi_direct.h",
# "wifi_direct_server_socket.h",
# "wifi_direct_socket.h",
# "wifi_hotspot.h",
# "wifi_hotspot_server_socket.h",
# "wifi_hotspot_socket.h",
# "wifi_lan.h",
# "wifi_lan_server_socket.h",
# "wifi_lan_socket.h",
# "wifi_medium.h",
# "wifi_socket.h",
],
deps = [
"//internal/platform:base",
@@ -138,10 +109,6 @@ cc_library(
cc_library(
name = "linux",
srcs = [
"avahi.cc",
# "ble_gatt_client.cc",
# "ble_gatt_server.cc",
# "ble_v2_medium.cc",
"bluetooth_adapter.cc",
"bluetooth_bluez_profile.cc",
"bluetooth_classic_socket.cc",
@@ -152,15 +119,8 @@ cc_library(
"bluetooth_pairing.cc",
"bluez.cc",
"bluez_agent.cc",
# "bluez_advertisement_monitor.cc",
# "bluez_gatt_characteristic_client.cc",
# "bluez_gatt_characteristic_server.cc",
# "bluez_gatt_service_server.cc",
# "bluez_le_advertisement.cc",
"dbus.cc",
"executor.cc",
# "network_manager.cc",
# "network_manager_active_connection.cc",
"platform.cc",
"preferences_manager.cc",
"preferences_repository.cc",
@@ -170,13 +130,6 @@ cc_library(
"system_clock.cc",
"thread_pool.cc",
"utils.cc",
# "wifi_direct.cc",
# "wifi_direct_server_socket.cc",
# "wifi_hotspot.cc",
# "wifi_hotspot_server_socket.cc",
# "wifi_lan.cc",
# "wifi_lan_server_socket.cc",
# "wifi_medium.cc",
],
linkopts = ["-lcurl"],
visibility = [
@@ -1,128 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#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) {
LOG(INFO) << __func__ << ": " << getObjectPath()
<< ": Found new item through the ServiceBrowser: "
<< "interface: " << interface << ", protocol: "
<< protocol << ", name: '" << name << "', type: '"
<< type << "', domain: '" << domain
<< "', flags: " << flags;
if (flags & kAvahiLookupResultLocal) {
LOG(INFO) << __func__ << ": Ignoring local service.";
return;
}
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
0);
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) {
LOG(WARNING) << " found invalid text attribute: " << attr_str;
continue;
}
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?
LOG(INFO) << __func__ << ": " << getObjectPath()
<< ": Item removed through the ServiceBrowser: "
<< "interface: " << interface << ", protocol: "
<< protocol << ", name: '" << name << "', type: '"
<< type << "', domain: '" << domain
<< "', flags: " << flags;
if (flags & kAvahiLookupResultLocal) {
LOG(INFO) << __func__ << ": Ignoring local service.";
return;
}
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) {
LOG(WARNING) << " found invalid text attribute: " << attr_str;
continue;
}
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) {
LOG(ERROR) << __func__ << ": " << getObjectPath()
<< ": ServiceBrowser reported a failure: " << error;
}
void ServiceBrowser::onAllForNow() {
LOG(INFO) << __func__ << ": " << getObjectPath()
<< ": notified via ServiceBrowser that all records have "
"been added for now";
}
void ServiceBrowser::onCacheExhausted() {
LOG(INFO) << __func__ << ": " << getObjectPath()
<< ": notified via ServiceBrowser of cache exhaustion";
}
} // namespace avahi
} // namespace linux
} // namespace nearby
@@ -1,127 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_AVAHI_H_
#define PLATFORM_IMPL_LINUX_AVAHI_H_
#include <memory>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/avahi/entrygroup_client.h"
#include "internal/platform/implementation/linux/generated/dbus/avahi/server2_client.h"
#include "internal/platform/implementation/linux/generated/dbus/avahi/servicebrowser_client.h"
#include "internal/platform/implementation/wifi_lan.h"
namespace nearby {
namespace linux {
namespace avahi {
class Server final
: public sdbus::ProxyInterfaces<org::freedesktop::Avahi::Server2_proxy> {
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 final
: public sdbus::ProxyInterfaces<org::freedesktop::Avahi::EntryGroup_proxy> {
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() {
LOG(INFO) << __func__ << ": Freeing entry group "
<< getObjectPath();
try {
Free();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "Free", e);
}
unregisterProxy();
}
protected:
void onStateChanged(const int32_t &state, const std::string &error) override {
}
};
class ServiceBrowser final
: 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,
std::shared_ptr<Server> avahi_server)
: ProxyInterfaces(system_bus, "org.freedesktop.Avahi",
service_browser_object_path),
discovery_cb_(std::move(callback)),
server_(avahi_server) {
registerProxy();
}
~ServiceBrowser() {
LOG(INFO) << __func__ << ": Freeing service browser "
<< getObjectPath();
try {
Free();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "Free", e);
}
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:
enum LookupResultFlags {
kAvahiLookupResultFlagCached = 1,
kAvahiLookupResultFlagWideArea = 2,
kAvahiLookupResultFlagMulticast = 4,
kAvahiLookupResultLocal = 8,
kAvahiLookupResultOurOwn = 16,
kAvahiLookupResultStatic = 32,
};
api::WifiLanMedium::DiscoveredServiceCallback discovery_cb_;
std::shared_ptr<Server> server_;
};
} // namespace avahi
} // namespace linux
} // namespace nearby
#endif
@@ -1,428 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <map>
#include <string>
#include <variant>
#include <sdbus-c++/Types.h>
#include "absl/strings/substitute.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/cancellation_flag_listener.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/ble_gatt_client.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_client.h"
#include "internal/platform/implementation/linux/bluez_gatt_service_client.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_client.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_client.h"
#include "internal/platform/implementation/linux/utils.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
bool GattClient::DiscoverServiceAndCharacteristics(
const Uuid &service_uuid, const std::vector<Uuid> &characteristic_uuids) {
return gatt_discovery_->DiscoverServiceAndCharacteristics(
peripheral_object_path_, service_uuid, characteristic_uuids,
discovery_cancel_);
}
absl::optional<api::ble_v2::GattCharacteristic> GattClient::GetCharacteristic(
const Uuid &service_uuid, const Uuid &characteristic_uuid) {
auto chr_proxy = gatt_discovery_->GetCharacteristic(
peripheral_object_path_, service_uuid, characteristic_uuid);
if (chr_proxy == nullptr) return std::nullopt;
api::ble_v2::GattCharacteristic chr;
chr.service_uuid = service_uuid;
chr.uuid = characteristic_uuid;
chr.property = api::ble_v2::GattCharacteristic::Property::kNone;
chr.permission = api::ble_v2::GattCharacteristic::Permission::kNone;
std::vector<std::string> flags;
try {
flags = chr_proxy->Flags();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(chr_proxy, "Flags", e);
return std::nullopt;
}
for (const auto &flag : flags) {
if (flag == "read") {
chr.property |= api::ble_v2::GattCharacteristic::Property::kRead;
chr.permission |= api::ble_v2::GattCharacteristic::Permission::kRead;
} else if (flag == "write") {
chr.property |= api::ble_v2::GattCharacteristic::Property::kWrite;
chr.permission |= api::ble_v2::GattCharacteristic::Permission::kWrite;
} else if (flag == "notify") {
chr.property |= api::ble_v2::GattCharacteristic::Property::kNotify;
} else if (flag == "indicate") {
chr.property |= api::ble_v2::GattCharacteristic::Property::kIndicate;
}
}
absl::MutexLock lock(&characteristics_mutex_);
characteristics_.emplace(chr, std::move(chr_proxy));
return chr;
}
absl::optional<std::string> GattClient::ReadCharacteristic(
const api::ble_v2::GattCharacteristic &characteristic) {
absl::ReaderMutexLock lock(&characteristics_mutex_);
if (characteristics_.count(characteristic) == 0) {
LOG(ERROR) << __func__ << ": Unknown characteristic '"
<< absl::Substitute("$0", characteristic) << "'";
return std::nullopt;
}
return std::visit(
[](auto &&chr) {
try {
auto value_bytes = chr->ReadValue({});
return std::optional<std::string>{
std::string(value_bytes.begin(), value_bytes.end())};
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(chr, "ReadValue", e);
return std::optional<std::string>();
}
},
characteristics_[characteristic]);
}
bool GattClient::WriteCharacteristic(
const api::ble_v2::GattCharacteristic &characteristic,
absl::string_view value, WriteType type) {
absl::ReaderMutexLock lock(&characteristics_mutex_);
if (characteristics_.count(characteristic) == 0) {
LOG(ERROR) << __func__ << ": Unknown characteristic '"
<< absl::Substitute("$0", characteristic) << "'";
return false;
}
return std::visit(
[value, type](auto &&chr) {
std::vector<uint8_t> value_bytes(value.begin(), value.end());
try {
chr->WriteValue(
value_bytes,
{{"type",
type == api::ble_v2::GattClient::WriteType::kWithResponse
? "request"
: "command"}});
return true;
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(chr, "WriteValue", e);
return false;
}
},
characteristics_[characteristic]);
}
bool GattClient::SetCharacteristicSubscription(
const api::ble_v2::GattCharacteristic &characteristic, bool enable,
absl::AnyInvocable<void(absl::string_view value)>
on_characteristic_changed_cb) {
absl::MutexLock lock(&characteristics_mutex_);
if (characteristics_.count(characteristic) == 0) {
LOG(ERROR) << __func__ << ": Unknown characteristic '"
<< absl::Substitute("$0", characteristic) << "'";
return false;
}
if (enable) {
auto subbed_chr = gatt_discovery_->GetSubscribedCharacteristic(
peripheral_object_path_, characteristic.service_uuid,
characteristic.uuid, std::move(on_characteristic_changed_cb));
if (subbed_chr == nullptr) return false;
try {
subbed_chr->StartNotify();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(subbed_chr, "StartNotify", e);
return false;
}
characteristics_[characteristic] = std::move(subbed_chr);
} else if (std::holds_alternative<
std::unique_ptr<bluez::SubscribedGattCharacteristicClient>>(
characteristics_[characteristic])) {
auto chr = gatt_discovery_->GetCharacteristic(peripheral_object_path_,
characteristic.service_uuid,
characteristic.uuid);
if (chr == nullptr) return false;
try {
chr->StopNotify();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(chr, "StopNotify", e);
return false;
}
characteristics_[characteristic] = std::move(chr);
}
return true;
}
void GattClient::Disconnect() {
absl::MutexLock lock(&disconnected_callback_mutex_);
if (!discovery_cancel_.Cancelled()) {
discovery_cancel_.Cancel();
if (*disconnected_callback_it_ != nullptr) (*disconnected_callback_it_)();
gatt_discovery_->RemovePeripheralConnection(peripheral_object_path_,
disconnected_callback_it_);
}
}
void BluezGattDiscovery::Shutdown() {
auto no_discovery = [&]() {
mutex_.AssertReaderHeld();
return pending_discovery_ == 0;
};
mutex_.Lock();
shutdown_ = true;
mutex_.Await(absl::Condition(&no_discovery));
mutex_.Unlock();
}
bool BluezGattDiscovery::InitializeKnownServices() {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return false;
}
absl::flat_hash_map<sdbus::ObjectPath, GattServiceClient> cached_services;
absl::MutexLock lock(&mutex_);
auto chr_it = std::find_if(
objects.cbegin(), objects.cend(),
[](std::pair<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
object) {
return object.second.count(
org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME) == 1;
});
for (; chr_it != objects.cend(); chr_it++) {
const auto &[path, ifaces] = *chr_it;
const auto &properties =
ifaces.at(org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME);
auto maybe_props = characteristicProperties(path, properties);
if (!maybe_props.has_value()) continue;
auto [chr_uuid, service_uuid, device_path] = *maybe_props;
discovered_characteristics_.emplace(
std::make_tuple(chr_uuid, service_uuid, device_path), path);
characteristics_properties_.emplace(
path, std::make_tuple(chr_uuid, service_uuid, device_path));
}
return true;
}
BluezGattDiscovery::CallbackIter BluezGattDiscovery::AddPeripheralConnection(
const sdbus::ObjectPath &device_object_path,
absl::AnyInvocable<void()> disconnected_callback_) {
absl::MutexLock lock(&peripheral_disconnected_callbacks_mutex_);
if (peripheral_disconnected_callbacks_.count(device_object_path) == 0)
peripheral_disconnected_callbacks_.emplace(
device_object_path, std::list<absl::AnyInvocable<void()>>{});
auto &list = peripheral_disconnected_callbacks_[device_object_path];
list.push_back(std::move(disconnected_callback_));
return list.begin();
}
void BluezGattDiscovery::RemovePeripheralConnection(
const sdbus::ObjectPath &device_object_path,
BluezGattDiscovery::CallbackIter cb) {
absl::MutexLock lock(&peripheral_disconnected_callbacks_mutex_);
auto it = peripheral_disconnected_callbacks_.find(device_object_path);
if (it != peripheral_disconnected_callbacks_.end()) {
it->second.erase(cb);
if (it->second.empty())
peripheral_disconnected_callbacks_.erase(device_object_path);
}
}
bool BluezGattDiscovery::DiscoverServiceAndCharacteristics(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const std::vector<Uuid> &characteristic_uuids, CancellationFlag &cancel) {
CancellationFlagListener cancel_listen(&cancel, [&]() {
mutex_.Lock();
mutex_.Unlock();
});
auto discovered = [this, device_object_path, service_uuid,
characteristic_uuids, &cancel]() {
mutex_.AssertReaderHeld();
return cancel.Cancelled() ||
std::all_of(
characteristic_uuids.cbegin(), characteristic_uuids.cend(),
[this, service_uuid, device_object_path](auto &chr_uuid) {
mutex_.AssertReaderHeld();
return discovered_characteristics_.count(
{service_uuid, chr_uuid, device_object_path}) == 1;
});
};
absl::ReaderMutexLock lock(&mutex_, absl::Condition(&discovered));
return !cancel.Cancelled();
}
std::unique_ptr<bluez::GattCharacteristicClient>
BluezGattDiscovery::GetCharacteristic(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const Uuid &characteristic_uuid) {
auto key =
std::make_tuple(service_uuid, characteristic_uuid, device_object_path);
absl::ReaderMutexLock lock(&mutex_);
auto path_it = discovered_characteristics_.find(key);
if (path_it == discovered_characteristics_.end()) {
LOG(ERROR) << __func__ << ": No characteristic known for device "
<< device_object_path << " with service "
<< std::string{service_uuid} << " and UUID "
<< std::string{characteristic_uuid};
return nullptr;
}
return std::make_unique<bluez::GattCharacteristicClient>(system_bus_,
path_it->second);
}
std::unique_ptr<bluez::GattCharacteristicClient>
BluezGattDiscovery::GetSubscribedCharacteristic(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const Uuid &characteristic_uuid,
absl::AnyInvocable<void(absl::string_view value)>
on_characteristic_changed_cb) {
auto key =
std::make_tuple(service_uuid, characteristic_uuid, device_object_path);
absl::ReaderMutexLock lock(&mutex_);
auto path_it = discovered_characteristics_.find(key);
if (path_it == discovered_characteristics_.end()) {
LOG(ERROR) << __func__ << ": No characteristic known for device "
<< device_object_path << " with service "
<< std::string{service_uuid} << " and UUID "
<< std::string{characteristic_uuid};
return nullptr;
}
return std::make_unique<bluez::SubscribedGattCharacteristicClient>(
system_bus_, device_object_path, std::move(on_characteristic_changed_cb));
}
std::optional<std::tuple<Uuid, Uuid, sdbus::ObjectPath>>
BluezGattDiscovery::characteristicProperties(
const sdbus::ObjectPath &path,
const std::map<std::string, sdbus::Variant> &properties) {
mutex_.AssertHeld();
const std::string &chr_uuid_str = properties.at("UUID");
auto chr_uuid = UuidFromString(chr_uuid_str);
if (!chr_uuid.has_value()) {
LOG(ERROR) << ": Couldn't parse UUID '" << chr_uuid_str
<< "' in characteristic " << path;
return std::nullopt;
}
const sdbus::ObjectPath &service_path = properties.at("Service");
if (cached_services_.count(service_path) == 0) {
cached_services_.emplace(
path, std::make_unique<GattServiceClient>(system_bus_, path));
}
auto &service = cached_services_.at(service_path);
nearby::Uuid service_uuid;
try {
const std::string &service_uuid_str = service->UUID();
auto service_uuid_maybe = UuidFromString(service_uuid_str);
if (!service_uuid_maybe.has_value()) {
LOG(ERROR) << ": Couldn't parse UUID '" << service_uuid_str
<< "' in service " << service_path;
return std::nullopt;
}
service_uuid = *service_uuid_maybe;
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(service, "UUID", e);
return std::nullopt;
}
sdbus::ObjectPath device_path;
try {
device_path = service->Device();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(service, "Device", e);
return std::nullopt;
}
return std::make_tuple(*chr_uuid, service_uuid, device_path);
}
void BluezGattDiscovery::onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) {
if (interfacesAndProperties.count(
org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME) == 0)
return;
const auto &properties = interfacesAndProperties.at(
org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME);
absl::MutexLock lock(&mutex_);
auto maybe_props = characteristicProperties(objectPath, properties);
if (!maybe_props.has_value()) return;
auto [chr_uuid, service_uuid, device_path] = *maybe_props;
discovered_characteristics_.emplace(
std::make_tuple(chr_uuid, service_uuid, device_path), objectPath);
characteristics_properties_.emplace(
objectPath, std::make_tuple(chr_uuid, service_uuid, device_path));
}
void BluezGattDiscovery::onInterfacesRemoved(
const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) {
auto begin = interfaces.cbegin();
auto end = interfaces.cend();
auto service_it =
std::find(begin, end, org::bluez::GattService1_proxy::INTERFACE_NAME);
if (service_it != end) {
absl::MutexLock lock(&mutex_);
cached_services_.erase(objectPath);
return;
}
auto chr_it = std::find(
begin, end, org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME);
if (chr_it != end) {
absl::MutexLock lock(&mutex_);
{
auto &props = characteristics_properties_.at(objectPath);
discovered_characteristics_.erase(props);
}
characteristics_properties_.erase(objectPath);
}
}
} // namespace linux
} // namespace nearby
@@ -1,210 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_GATT_CLIENT_H_
#define PLATFORM_IMPL_LINUX_API_BLE_GATT_CLIENT_H_
#include <list>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Types.h>
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_client.h"
#include "internal/platform/implementation/linux/bluez_gatt_service_client.h"
namespace nearby {
namespace linux {
class BluezGattDiscovery final : public bluez::BluezObjectManager {
public:
explicit BluezGattDiscovery(std::shared_ptr<sdbus::IConnection> system_bus)
: bluez::BluezObjectManager(*system_bus),
system_bus_(system_bus),
shutdown_(false),
pending_discovery_(0) {}
~BluezGattDiscovery() override { Shutdown(); }
bool InitializeKnownServices() ABSL_LOCKS_EXCLUDED(mutex_);
using CallbackIter = typename std::list<absl::AnyInvocable<void()>>::iterator;
CallbackIter AddPeripheralConnection(
const sdbus::ObjectPath &device_object_path,
absl::AnyInvocable<void()> disconnected_callback_)
ABSL_LOCKS_EXCLUDED(peripheral_disconnected_callbacks_mutex_);
void RemovePeripheralConnection(const sdbus::ObjectPath &device_object_path,
BluezGattDiscovery::CallbackIter cb)
ABSL_LOCKS_EXCLUDED(peripheral_disconnected_callbacks_mutex_);
bool DiscoverServiceAndCharacteristics(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const std::vector<Uuid> &characteristic_uuids, CancellationFlag &cancel)
ABSL_LOCKS_EXCLUDED(mutex_);
std::unique_ptr<bluez::GattCharacteristicClient> GetCharacteristic(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const Uuid &characteristic_uuid) ABSL_LOCKS_EXCLUDED(mutex_);
std::unique_ptr<bluez::GattCharacteristicClient> GetSubscribedCharacteristic(
const sdbus::ObjectPath &device_object_path, const Uuid &service_uuid,
const Uuid &characteristic_uuid,
absl::AnyInvocable<void(absl::string_view value)>
on_characteristic_changed_cb) ABSL_LOCKS_EXCLUDED(mutex_);
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override ABSL_LOCKS_EXCLUDED(mutex_);
void onInterfacesRemoved(const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override
ABSL_LOCKS_EXCLUDED(mutex_);
private:
std::optional<std::tuple<Uuid, Uuid, sdbus::ObjectPath>>
characteristicProperties(
const sdbus::ObjectPath &path,
const std::map<std::string, sdbus::Variant> &properties)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void Shutdown() ABSL_LOCKS_EXCLUDED(mutex_);
std::shared_ptr<sdbus::IConnection> system_bus_;
absl::Mutex peripheral_disconnected_callbacks_mutex_;
absl::flat_hash_map<sdbus::ObjectPath, std::list<absl::AnyInvocable<void()>>>
peripheral_disconnected_callbacks_
ABSL_GUARDED_BY(peripheral_disconnected_callbacks_mutex_);
absl::Mutex mutex_;
absl::flat_hash_map<sdbus::ObjectPath, std::unique_ptr<GattServiceClient>>
cached_services_ ABSL_GUARDED_BY(mutex_);
// Tuple order: service uuid, characteristic uuid, device object path
absl::flat_hash_map<std::tuple<Uuid, Uuid, sdbus::ObjectPath>,
sdbus::ObjectPath>
discovered_characteristics_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<sdbus::ObjectPath,
std::tuple<Uuid, Uuid, sdbus::ObjectPath>>
characteristics_properties_ ABSL_GUARDED_BY(mutex_);
bool shutdown_ ABSL_GUARDED_BY(mutex_);
std::size_t pending_discovery_ ABSL_GUARDED_BY(mutex_);
};
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt
//
// Representation of a client GATT connection to a remote GATT server.
class GattClient : public api::ble_v2::GattClient {
public:
GattClient(const GattClient &) = delete;
GattClient(GattClient &&) = delete;
GattClient &operator=(const GattClient &) = delete;
GattClient &operator=(GattClient &&) = delete;
explicit GattClient(std::shared_ptr<sdbus::IConnection> system_bus,
const sdbus::ObjectPath &peripheral_object_path,
std::shared_ptr<BluezGattDiscovery> gatt_discovery,
absl::AnyInvocable<void()> disconnected_callback)
: system_bus_(std::move(system_bus)),
peripheral_object_path_(peripheral_object_path),
gatt_discovery_(std::move(gatt_discovery)),
discovery_cancel_(false) {
disconnected_callback_it_ = gatt_discovery->AddPeripheralConnection(
peripheral_object_path_, std::move(disconnected_callback));
}
~GattClient() override {
absl::MutexLock lock(&disconnected_callback_mutex_);
if (!discovery_cancel_.Cancelled()) {
discovery_cancel_.Cancel();
gatt_discovery_->RemovePeripheralConnection(peripheral_object_path_,
disconnected_callback_it_);
}
}
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#discoverServices()
//
// Discovers available service and characteristics on this connection.
// Returns whether or not discovery finished successfully.
//
// This function should block until discovery has finished.
bool DiscoverServiceAndCharacteristics(
const Uuid &service_uuid,
const std::vector<Uuid> &characteristic_uuids) override;
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getService(java.util.UUID)
// https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html#getCharacteristic(java.util.UUID)
//
// Retrieves a GATT characteristic. On error, does not return a value.
//
// DiscoverServiceAndCharacteristics() should be called before this method to
// fetch all available services and characteristics first.
//
// It is okay for duplicate services to exist, as long as the specified
// characteristic UUID is unique among all services of the same UUID.
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<api::ble_v2::GattCharacteristic> GetCharacteristic(
const Uuid &service_uuid, const Uuid &characteristic_uuid) override
ABSL_LOCKS_EXCLUDED(characteristics_mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#readCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#getValue()
// NOLINTNEXTLINE(google3-legacy-absl-backports)
absl::optional<std::string> ReadCharacteristic(
const api::ble_v2::GattCharacteristic &characteristic) override
ABSL_LOCKS_EXCLUDED(characteristics_mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[])
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
//
// Sends a remote characteristic write request to the server and returns
// whether or not it was successful.
bool WriteCharacteristic(
const api::ble_v2::GattCharacteristic &characteristic,
absl::string_view value, WriteType type) override
ABSL_LOCKS_EXCLUDED(characteristics_mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic,%20boolean)
//
// Enable or disable notifications/indications for a given characteristic.
bool SetCharacteristicSubscription(
const api::ble_v2::GattCharacteristic &characteristic, bool enable,
absl::AnyInvocable<void(absl::string_view value)>
on_characteristic_changed_cb) override
ABSL_LOCKS_EXCLUDED(characteristics_mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#disconnect()
void Disconnect() override;
private:
std::shared_ptr<sdbus::IConnection> system_bus_;
sdbus::ObjectPath peripheral_object_path_;
std::shared_ptr<BluezGattDiscovery> gatt_discovery_;
absl::Mutex disconnected_callback_mutex_;
BluezGattDiscovery::CallbackIter disconnected_callback_it_
ABSL_GUARDED_BY(disconnected_callback_mutex_);
CancellationFlag discovery_cancel_;
using CharacteristicProxy =
std::variant<std::unique_ptr<bluez::GattCharacteristicClient>,
std::unique_ptr<bluez::SubscribedGattCharacteristicClient>>;
absl::Mutex characteristics_mutex_;
absl::flat_hash_map<api::ble_v2::GattCharacteristic, CharacteristicProxy>
characteristics_ ABSL_GUARDED_BY(characteristics_mutex_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,147 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/implementation/linux/ble_gatt_server.h"
#include "absl/strings/substitute.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_server.h"
#include "internal/platform/implementation/linux/bluez_gatt_manager.h"
#include "internal/platform/implementation/linux/bluez_gatt_service_server.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_server.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
absl::optional<api::ble_v2::GattCharacteristic>
GattServer::CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) {
absl::MutexLock lock(&services_mutex_);
if (services_.count(service_uuid) == 1) {
if (services_[service_uuid]->AddCharacteristic(
service_uuid, characteristic_uuid, permission, property)) {
api::ble_v2::GattCharacteristic characteristic{
characteristic_uuid, service_uuid, permission, property};
return characteristic;
}
return std::nullopt;
}
auto count = services_.size();
auto service = std::make_unique<bluez::GattServiceServer>(
system_bus_, count, service_uuid, server_cb_, devices_);
try {
service->emitInterfacesAddedSignal(
{org::bluez::GattService1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error& e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesAdded signal for object path "
<< service->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
return std::nullopt;
}
if (service->AddCharacteristic(service_uuid, characteristic_uuid, permission,
property)) {
bluez::GattManager manager(system_bus_, adapter_.GetObjectPath());
try {
LOG(INFO) << __func__ << ": registering service "
<< service->getObjectPath();
manager.RegisterApplication("/", {});
} catch (const sdbus::Error& e) {
DBUS_LOG_METHOD_CALL_ERROR(&manager, "RegisterApplication", e);
return std::nullopt;
}
services_.insert({service_uuid, std::move(service)});
api::ble_v2::GattCharacteristic characteristic{
characteristic_uuid, service_uuid, permission, property};
return characteristic;
}
return std::nullopt;
}
bool GattServer::UpdateCharacteristic(
const api::ble_v2::GattCharacteristic& characteristic,
const nearby::ByteArray& value) {
std::shared_ptr<bluez::GattCharacteristicServer> chr = nullptr;
{
absl::ReaderMutexLock lock(&services_mutex_);
if (services_.count(characteristic.service_uuid) == 0) {
LOG(ERROR) << __func__ << ": GATT Service "
<< std::string{characteristic.service_uuid}
<< " doesn't exist";
return false;
}
chr = services_[characteristic.service_uuid]->GetCharacteristic(
characteristic.uuid);
}
if (chr == nullptr) {
LOG(ERROR) << __func__ << ": Characteristic "
<< std::string{characteristic.uuid}
<< " does not exist under service "
<< std::string{characteristic.service_uuid};
return false;
}
assert(chr != nullptr);
chr->Update(value);
return true;
}
absl::Status GattServer::NotifyCharacteristicChanged(
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
const ByteArray& new_value) {
std::shared_ptr<bluez::GattCharacteristicServer> chr = nullptr;
{
absl::ReaderMutexLock lock(&services_mutex_);
if (services_.count(characteristic.service_uuid) == 0) {
return absl::NotFoundError(
absl::Substitute("Service $0 doesn't exist",
std::string{characteristic.service_uuid}));
}
chr = services_[characteristic.service_uuid]->GetCharacteristic(
characteristic.uuid);
}
if (chr == nullptr) {
return absl::NotFoundError(
absl::Substitute("characteristic $0 doesn't exist under service $1",
std::string{characteristic.uuid},
std::string{characteristic.service_uuid}));
}
return chr->NotifyChanged(confirm, new_value);
}
void GattServer::Stop() {
bluez::GattManager manager(system_bus_, adapter_.GetObjectPath());
absl::MutexLock lock(&services_mutex_);
for (auto& [uuid, service] : services_) {
LOG(INFO) << __func__ << ": Unregistering service "
<< service->getObjectPath();
try {
manager.UnregisterApplication("/");
} catch (const sdbus::Error& e) {
DBUS_LOG_METHOD_CALL_ERROR(&manager, "UnregisterApplication", e);
}
}
// services_.clear();
}
} // namespace linux
} // namespace nearby
@@ -1,96 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_
#define PLATFORM_IMPL_LINUX_API_BLE_GATT_SERVER_H_
#include <memory>
#include <sdbus-c++/IConnection.h>
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/optional.h"
#include "internal/platform/bluetooth_utils.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez_gatt_service_server.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
class LocalBlePeripheral : public api::ble_v2::BlePeripheral {
public:
explicit LocalBlePeripheral(BluetoothAdapter& adapter) : adapter_(adapter) {
unique_id_ = BluetoothUtils::ToNumber(adapter_.GetMacAddress());
}
std::string GetAddress() const override { return adapter_.GetMacAddress(); }
UniqueId GetUniqueId() const override { return unique_id_; }
private:
BluetoothAdapter adapter_;
UniqueId unique_id_;
};
class GattServer : public api::ble_v2::GattServer {
public:
GattServer(const GattServer&) = delete;
GattServer(GattServer&&) = delete;
GattServer& operator=(const GattServer&) = delete;
GattServer& operator=(GattServer&&) = delete;
explicit GattServer(sdbus::IConnection& system_bus, BluetoothAdapter& adapter,
std::shared_ptr<BluetoothDevices> devices,
api::ble_v2::ServerGattConnectionCallback server_cb)
: system_bus_(system_bus),
devices_(std::move(devices)),
adapter_(adapter),
local_peripheral_(adapter_),
server_cb_(std::make_shared<api::ble_v2::ServerGattConnectionCallback>(
std::move(server_cb))) {}
~GattServer() override = default;
api::ble_v2::BlePeripheral& GetBlePeripheral() override {
return local_peripheral_;
}
absl::optional<api::ble_v2::GattCharacteristic> CreateCharacteristic(
const Uuid& service_uuid, const Uuid& characteristic_uuid,
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) override;
bool UpdateCharacteristic(
const api::ble_v2::GattCharacteristic& characteristic,
const nearby::ByteArray& value) override;
absl::Status NotifyCharacteristicChanged(
const api::ble_v2::GattCharacteristic& characteristic, bool confirm,
const ByteArray& new_value) override;
void Stop() override;
private:
sdbus::IConnection& system_bus_;
std::shared_ptr<BluetoothDevices> devices_;
BluetoothAdapter adapter_;
LocalBlePeripheral local_peripheral_;
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
absl::Mutex services_mutex_;
absl::flat_hash_map<Uuid, std::unique_ptr<bluez::GattServiceServer>> services_
ABSL_GUARDED_BY(services_mutex_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,73 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_API_BLE_MEDIUM_H_
#include "internal/platform/implementation/ble.h"
namespace nearby {
namespace linux {
// Container of operations that can be performed over the BLE medium.
class BleMedium : public api::BleMedium {
public:
BleMedium() {}
~BleMedium() = default;
bool StartAdvertising(
const std::string &service_id, const ByteArray &advertisement_bytes,
const std::string &fast_advertisement_service_uuid) override {
return false;
}
bool StopAdvertising(const std::string &service_id) override { return false; }
// Returns true once the BLE scan has been initiated.
bool StartScanning(const std::string &service_id,
const std::string &fast_advertisement_service_uuid,
DiscoveredPeripheralCallback callback) override {
return false;
}
// Returns true once BLE scanning for service_id is well and truly stopped;
// after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
bool StopScanning(const std::string &service_id) override { return false; }
// Callback that is invoked when a new connection is accepted.
using AcceptedConnectionCallback = absl::AnyInvocable<void(
api::BleSocket &socket, const std::string &service_id)>;
// Returns true once BLE socket connection requests to service_id can be
// accepted.
bool StartAcceptingConnections(const std::string &service_id,
AcceptedConnectionCallback callback) override {
return false;
}
bool StopAcceptingConnections(const std::string &service_id) override {
return false;
}
// Connects to a BLE peripheral.
// On success, returns a new BleSocket.
// On error, returns nullptr.
std::unique_ptr<api::BleSocket> Connect(
api::BlePeripheral &peripheral, const std::string &service_id,
CancellationFlag *cancellation_flag) override {
return nullptr;
}
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,480 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <cassert>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/ble_gatt_client.h"
#include "internal/platform/implementation/linux/ble_gatt_server.h"
#include "internal/platform/implementation/linux/ble_v2_medium.h"
#include "internal/platform/implementation/linux/bluetooth_classic_device.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
#include "internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h"
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_server.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_manager_client.h"
namespace nearby {
namespace linux {
BleV2Medium::BleV2Medium(BluetoothAdapter &adapter)
: system_bus_(adapter.GetConnection()),
adapter_(adapter),
devices_(std::make_unique<BluetoothDevices>(
system_bus_, adapter_.GetObjectPath(), observers_)),
gatt_discovery_(std::make_shared<BluezGattDiscovery>(system_bus_)),
root_object_manager_(std::make_unique<RootObjectManager>(*system_bus_)),
adv_monitor_manager_(
bluez::AdvertisementMonitorManager::
DiscoverAdvertisementMonitorManager(*system_bus_, adapter_)),
adv_manager_(std::make_unique<bluez::LEAdvertisementManager>(*system_bus_,
adapter)),
cur_adv_(nullptr) {
if (adv_monitor_manager_) {
LOG(INFO)
<< __func__
<< ": Registering path / with AdvertisementMonitorManager at "
<< adv_monitor_manager_->getObjectPath();
try {
adv_monitor_manager_->RegisterMonitor("/");
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(adv_monitor_manager_, "RegisterMonitor", e);
}
}
if (gatt_discovery_->InitializeKnownServices()) {
LOG(ERROR) << __func__
<< ": Could not initialize known GATT services";
}
}
bool BleV2Medium::StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters) {
if (!adapter_.IsEnabled()) {
LOG(WARNING) << "BLE cannot start advertising because the "
"bluetooth adapter is not enabled.";
return false;
}
if (advertising_data.service_data.empty()) {
LOG(WARNING)
<< "BLE cannot start to advertise due to invalid service data.";
return false;
}
absl::MutexLock lock(&cur_adv_mutex_);
if (cur_adv_ != nullptr) {
LOG(ERROR) << __func__
<< "Advertising is already enabled for this medium.";
return false;
}
cur_adv_ = bluez::LEAdvertisement::CreateLEAdvertisement(
*system_bus_, advertising_data, advertise_set_parameters);
LOG(INFO) << __func__ << ": Registering advertisement "
<< cur_adv_->getObjectPath() << " on bluetooth adapter "
<< adapter_.GetObjectPath();
try {
adv_manager_->RegisterAdvertisement(cur_adv_->getObjectPath(), {});
} catch (const sdbus::Error &e) {
cur_adv_ = nullptr;
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "RegisterAdvertisement", e);
return false;
}
return true;
}
bool BleV2Medium::StopAdvertising() {
absl::MutexLock lock(&cur_adv_mutex_);
if (cur_adv_ == nullptr) {
LOG(ERROR) << __func__ << ": Advertising is not enabled.";
return false;
}
LOG(INFO) << __func__ << "Unregistering advertisement object "
<< cur_adv_->getObjectPath();
try {
adv_manager_->UnregisterAdvertisement(cur_adv_->getObjectPath());
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisement", e);
return false;
}
cur_adv_ = nullptr;
return true;
}
std::unique_ptr<api::ble_v2::BleMedium::AdvertisingSession>
BleV2Medium::StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters,
AdvertisingCallback callback) {
if (!adapter_.IsEnabled()) {
LOG(WARNING) << ": BLE cannot start advertising because the "
"bluetooth adapter is not enabled.";
return nullptr;
}
if (advertising_data.service_data.empty()) {
LOG(WARNING)
<< ": BLE cannot start to advertise due to invalid service data.";
return nullptr;
}
std::shared_ptr<sdbus::IProxy> proxy =
sdbus::createProxy(*system_bus_, "org.bluez", adapter_.GetObjectPath());
proxy->finishRegistration();
std::shared_ptr<AdvertisingCallback> shared_cb =
std::make_shared<AdvertisingCallback>(std::move(callback));
absl::MutexLock lock(&advs_mutex_);
advs_.push_front(bluez::LEAdvertisement::CreateLEAdvertisement(
*system_bus_, advertising_data, advertise_set_parameters));
auto adv_it = advs_.begin();
auto pending_call =
proxy->callMethodAsync("RegisterAdvertisement")
.onInterface(org::bluez::LEAdvertisingManager1_proxy::INTERFACE_NAME)
.withArguments((*adv_it)->getObjectPath(),
std::map<std::string, sdbus::Variant>{})
.uponReplyInvoke(
[this, proxy, shared_cb, adv_it](const sdbus::Error *error) {
if (error != nullptr && error->isValid()) {
{
absl::MutexLock lock(&advs_mutex_);
advs_.erase(adv_it);
}
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_,
"RegisterAdvertisement", *error);
auto name = error->getName();
std::string msg = error->getMessage();
absl::Status status;
if (name == "org.bluez.Error.InvalidArguments" ||
name == "org.bluez.Error.InvalidLength") {
status = absl::InvalidArgumentError(msg);
} else if (name == "org.bluez.Error.AlreadyExists") {
status = absl::AlreadyExistsError(msg);
} else if (name == "org.bluez.Error.NotPermitted") {
status = absl::ResourceExhaustedError(msg);
} else {
status = absl::UnknownError(msg);
}
shared_cb->start_advertising_result(std::move(status));
} else {
shared_cb->start_advertising_result(absl::OkStatus());
}
});
absl::AnyInvocable<absl::Status()> stop_adv = [&, adv_it]() {
LOG(INFO) << __func__ << ": Unregistering advertisement object "
<< (*adv_it)->getObjectPath();
absl::MutexLock lock(&advs_mutex_);
try {
adv_manager_->UnregisterAdvertisement((*adv_it)->getObjectPath());
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(adv_manager_, "UnregisterAdvertisement", e);
return absl::UnknownError(e.getMessage());
}
advs_.erase(adv_it);
return absl::OkStatus();
};
return std::make_unique<api::ble_v2::BleMedium::AdvertisingSession>(
api::ble_v2::BleMedium::AdvertisingSession{std::move(stop_adv)});
}
std::unique_ptr<api::ble_v2::GattServer> BleV2Medium::StartGattServer(
api::ble_v2::ServerGattConnectionCallback callback) {
return std::make_unique<GattServer>(*system_bus_, adapter_, devices_,
std::move(callback));
}
std::unique_ptr<api::ble_v2::GattClient> BleV2Medium::ConnectToGattServer(
api::ble_v2::BlePeripheral &peripheral,
api::ble_v2::TxPowerLevel tx_power_level,
api::ble_v2::ClientGattConnectionCallback callback) {
auto path = bluez::device_object_path(adapter_.GetObjectPath(),
peripheral.GetAddress());
return std::make_unique<GattClient>(system_bus_, path, gatt_discovery_,
std::move(callback.disconnected_cb));
}
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
try {
auto supported_channels = adv_manager_->SupportedSecondaryChannels();
return !supported_channels.empty();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(adv_manager_, "SupportedSecondaryChannels", e);
return false;
}
}
bool BleV2Medium::StartLEDiscovery() {
std::map<std::string, sdbus::Variant> filter;
filter["Transport"] = "auto";
auto &adapter = adapter_.GetBluezAdapterObject();
try {
adapter.SetDiscoveryFilter(filter);
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "SetDiscoveryFilter", e);
return false;
}
try {
LOG(INFO) << __func__ << ": Starting LE discovery on "
<< adapter.getObjectPath();
adapter.StartDiscovery();
} catch (const sdbus::Error &e) {
if (e.getName() != "org.bluez.Error.InProgress") {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StartDiscovery", e);
return false;
}
}
return true;
}
bool BleV2Medium::StartScanning(const Uuid &service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
ScanCallback callback) {
if (cur_monitored_service_uuid_.has_value()) {
LOG(ERROR) << __func__
<< ": A sync scanning session is already active for "
<< std::string{*cur_monitored_service_uuid_};
return false;
}
if (adv_monitor_manager_ == nullptr) {
LOG(WARNING) << __func__
<< ": Advertising monitor not supported by BlueZ";
// TODO: Implement manual monitoring.
return false;
}
if (!MonitorManagerSupportsOr()) {
LOG(WARNING)
<< __func__
<< ": \"or_patterns\" not supported by AdvertisementMonitorManager";
// TODO: Implement manual monitoring.
return false;
}
absl::MutexLock lock(&active_adv_monitors_mutex_);
if (active_adv_monitors_.count(service_uuid) == 1) {
LOG(ERROR) << __func__ << ": an advertising session for service "
<< std::string{service_uuid} << " already exists";
return false;
}
auto monitor = std::make_unique<bluez::AdvertisementMonitor>(
*system_bus_, service_uuid, tx_power_level, "or_patterns", devices_,
std::move(callback));
try {
monitor->emitInterfacesAddedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesAdded signal for object path "
<< monitor->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
return false;
}
auto device_watcher = std::make_unique<DeviceWatcher>(
*system_bus_, adapter_.GetObjectPath(), devices_);
if (!StartLEDiscovery()) {
LOG(ERROR) << __func__
<< ": Could not start LE discovery on adapter "
<< adapter_.GetObjectPath();
device_watcher = nullptr;
try {
monitor->emitInterfacesRemovedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesRemoved signal for object path "
<< monitor->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
}
return false;
}
active_adv_monitors_[service_uuid] =
std::make_pair(std::move(monitor), std::move(device_watcher));
cur_monitored_service_uuid_ = service_uuid;
return true;
}
bool BleV2Medium::StopScanning() {
if (!cur_monitored_service_uuid_.has_value()) {
LOG(ERROR) << __func__
<< ": No sync scanning session is currently active.";
return false;
}
if (adv_monitor_manager_ == nullptr) {
// TODO: Implement manual monitoring.
return false;
}
auto &adapter = adapter_.GetBluezAdapterObject();
LOG(INFO) << __func__ << ": Stopping discovery for adapter "
<< adapter.getObjectPath();
try {
adapter.StopDiscovery();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
}
absl::MutexLock lock(&active_adv_monitors_mutex_);
auto monitor_it = active_adv_monitors_.find(*cur_monitored_service_uuid_);
assert(monitor_it != active_adv_monitors_.end());
{
auto &[_uuid, session] = *monitor_it;
auto &[adv_monitor, _watcher] = session;
LOG(INFO) << __func__ << ": Removing advertising monitor "
<< adv_monitor->getObjectPath();
adv_monitor->emitInterfacesRemovedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
}
active_adv_monitors_.erase(monitor_it);
cur_monitored_service_uuid_ = std::nullopt;
return true;
}
std::unique_ptr<api::ble_v2::BleMedium::ScanningSession>
BleV2Medium::StartScanning(const Uuid &service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
ScanningCallback callback) {
if (adv_monitor_manager_ == nullptr) {
// TODO: Implement manual monitoring.
return nullptr;
}
absl::MutexLock lock(&active_adv_monitors_mutex_);
if (active_adv_monitors_.count(service_uuid) == 1) {
LOG(ERROR) << __func__ << ": Service " << std::string{service_uuid}
<< " is already being advertised";
return nullptr;
}
auto monitor = std::make_unique<bluez::AdvertisementMonitor>(
*system_bus_, service_uuid, tx_power_level, "or_patterns", devices_,
std::move(callback));
try {
monitor->emitInterfacesAddedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesAdded signal for object path "
<< monitor->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
return nullptr;
}
auto device_watcher = std::make_unique<DeviceWatcher>(
*system_bus_, adapter_.GetObjectPath(), devices_);
if (!StartLEDiscovery()) {
LOG(ERROR) << __func__
<< ": Could not start LE discovery on adapter "
<< adapter_.GetObjectPath();
try {
monitor->emitInterfacesRemovedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesRemoved signal for object path "
<< monitor->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
}
return nullptr;
}
active_adv_monitors_[service_uuid] =
std::make_pair(std::move(monitor), std::move(device_watcher));
return std::make_unique<ScanningSession>(
ScanningSession{.stop_scanning = [this, service_uuid]() {
absl::MutexLock lock(&active_adv_monitors_mutex_);
if (active_adv_monitors_.count(service_uuid) == 0) {
LOG(ERROR)
<< __func__ << ": Advertising monitor for service "
<< std::string{service_uuid} << " does not exist anymore";
return absl::NotFoundError(
"Advertising monitor for this service does not exist");
}
auto &[monitor, watcher] = active_adv_monitors_[service_uuid];
try {
monitor->emitInterfacesRemovedSignal(
{org::bluez::AdvertisementMonitor1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesRemoved signal for object path "
<< monitor->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
}
auto &adapter = adapter_.GetBluezAdapterObject();
absl::Status status;
try {
adapter.StopDiscovery();
status = absl::OkStatus();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&adapter, "StopDiscovery", e);
status = absl::InternalError(e.getMessage());
}
active_adv_monitors_.erase(service_uuid);
return status;
}});
}
bool BleV2Medium::GetRemotePeripheral(const std::string &mac_address,
GetRemotePeripheralCallback callback) {
auto device = devices_->get_device_by_address(mac_address);
if (device == nullptr) return false;
callback(*device);
return true;
}
bool BleV2Medium::GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
GetRemotePeripheralCallback callback) {
auto device = devices_->get_device_by_unique_id(id);
if (device == nullptr) return false;
callback(*device);
return true;
}
} // namespace linux
} // namespace nearby
@@ -1,144 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_API_BLE_V2_MEDIUM_H_
#include <memory>
#include <sdbus-c++/IConnection.h>
#include "absl/base/attributes.h"
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/ble_gatt_client.h"
#include "internal/platform/implementation/linux/ble_v2_server_socket.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
#include "internal/platform/implementation/linux/bluez_advertisement_monitor_manager.h"
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
class BleV2Medium final : public api::ble_v2::BleMedium {
public:
BleV2Medium(const BleV2Medium &) = delete;
BleV2Medium(BleV2Medium &&) = delete;
BleV2Medium &operator=(const BleV2Medium &) = delete;
BleV2Medium &operator=(BleV2Medium &&) = delete;
explicit BleV2Medium(BluetoothAdapter &adapter);
~BleV2Medium() override = default;
bool StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters) override
ABSL_LOCKS_EXCLUDED(cur_adv_mutex_);
std::unique_ptr<AdvertisingSession> StartAdvertising(
const api::ble_v2::BleAdvertisementData &advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters,
AdvertisingCallback callback) ABSL_LOCKS_EXCLUDED(advs_mutex_) override;
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(advs_mutex_);
bool StartScanning(const Uuid &service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
ScanCallback callback) override
ABSL_LOCKS_EXCLUDED(active_adv_monitors_mutex_);
bool StopScanning() override ABSL_LOCKS_EXCLUDED(active_adv_monitors_mutex_);
std::unique_ptr<ScanningSession> StartScanning(
const Uuid &service_uuid, api::ble_v2::TxPowerLevel tx_power_level,
ScanningCallback callback) override;
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
api::ble_v2::ServerGattConnectionCallback callback) override;
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
api::ble_v2::BlePeripheral &peripheral,
api::ble_v2::TxPowerLevel tx_power_level,
api::ble_v2::ClientGattConnectionCallback callback) override;
std::unique_ptr<api::ble_v2::BleServerSocket> OpenServerSocket(
const std::string &service_id) override {
return std::make_unique<BleV2ServerSocket>();
}
std::unique_ptr<api::ble_v2::BleSocket> Connect(
const std::string &service_id, api::ble_v2::TxPowerLevel tx_power_level,
api::ble_v2::BlePeripheral &peripheral,
CancellationFlag *cancellation_flag) override {
return nullptr;
}
bool IsExtendedAdvertisementsAvailable() override;
bool GetRemotePeripheral(const std::string &mac_address,
GetRemotePeripheralCallback callback) override;
bool GetRemotePeripheral(api::ble_v2::BlePeripheral::UniqueId id,
GetRemotePeripheralCallback callback) override;
private:
bool StartLEDiscovery();
bool MonitorManagerSupportsOr() {
std::vector<std::string> supported_types;
try {
supported_types = adv_monitor_manager_->SupportedMonitorTypes();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(adv_monitor_manager_, "SupportedMonitorTypes",
e);
return false;
}
auto is_supported_type = [](std::string pattern) {
return pattern == "or_patterns";
};
auto end = supported_types.cend();
return std::find_if(supported_types.cbegin(), end, is_supported_type) !=
end;
}
std::shared_ptr<sdbus::IConnection> system_bus_;
BluetoothAdapter adapter_;
ObserverList<api::BluetoothClassicMedium::Observer> observers_ = {};
std::shared_ptr<BluetoothDevices> devices_;
std::shared_ptr<BluezGattDiscovery> gatt_discovery_;
std::unique_ptr<RootObjectManager> root_object_manager_;
std::unique_ptr<bluez::AdvertisementMonitorManager> adv_monitor_manager_;
absl::Mutex active_adv_monitors_mutex_;
absl::flat_hash_map<
Uuid,
std::pair<std::unique_ptr<bluez::AdvertisementMonitor>, std::unique_ptr<DeviceWatcher>>>
active_adv_monitors_ ABSL_GUARDED_BY(active_adv_monitors_mutex_);
// Used by the synchronous variant of StartScanning
std::optional<Uuid> cur_monitored_service_uuid_;
std::unique_ptr<bluez::LEAdvertisementManager> adv_manager_;
absl::Mutex cur_adv_mutex_;
std::unique_ptr<bluez::LEAdvertisement> cur_adv_
ABSL_GUARDED_BY(cur_adv_mutex_);
absl::Mutex advs_mutex_;
std::list<std::unique_ptr<bluez::LEAdvertisement>> advs_
ABSL_GUARDED_BY(advs_mutex_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,42 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLE_V2_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_API_BLE_V2_SERVER_SOCKET_H_
#include "absl/synchronization/notification.h"
#include "internal/platform/implementation/ble_v2.h"
namespace nearby {
namespace linux {
class BleV2ServerSocket final : public api::ble_v2::BleServerSocket {
public:
std::unique_ptr<api::ble_v2::BleSocket> Accept() override {
stopped_.WaitForNotification();
return nullptr;
}
Exception Close() override {
if (stopped_.HasBeenNotified()) return {Exception::kIo};
stopped_.Notify();
return {Exception::kSuccess};
}
private:
absl::Notification stopped_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -29,7 +29,6 @@
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/base/observer_list.h"
// #include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/linux/bluez_device.h"
#include "internal/platform/implementation/linux/dbus.h"
@@ -39,7 +38,6 @@ namespace nearby {
namespace linux {
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
// TODO: This used to inherit from ble_v2::BlePeripheral. Removed that since APIs have now changed
class BluetoothDevice : public api::BluetoothDevice {
public:
using UniqueId = std::uint64_t;
@@ -49,15 +49,6 @@ class BluetoothDevices final {
std::shared_ptr<BluetoothDevice> get_device_by_path(const sdbus::ObjectPath &)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
std::shared_ptr<BluetoothDevice> get_device_by_address(const std::string &);
std::shared_ptr<BluetoothDevice> get_device_by_unique_id(
api::ble_v2::BlePeripheral::UniqueId id) {
// TODO: Should probably remove BlePeripheral stuff from here but we can keep it since we can convert to/from
// uint64_t
MacAddress tmp;
MacAddress::FromUint64(id, tmp);
return get_device_by_address(tmp.ToString());
}
std::shared_ptr<MonitoredBluetoothDevice> add_new_device(sdbus::ObjectPath)
ABSL_LOCKS_EXCLUDED(devices_by_path_lock_);
@@ -39,41 +39,6 @@ sdbus::ObjectPath adapter_object_path(absl::string_view name) {
return absl::Substitute("/org/bluez/$0", name);
}
sdbus::ObjectPath gatt_service_path(size_t num) {
return absl::Substitute("$0/service$1", NEARBY_BLE_GATT_PATH_ROOT, num);
}
sdbus::ObjectPath gatt_characteristic_path(
const sdbus::ObjectPath &service_path, size_t num) {
return absl::Substitute("$0/char$1", service_path, num);
}
sdbus::ObjectPath ble_advertisement_path(size_t num) {
return absl::Substitute("/com/google/nearby/medium/ble/advertisement/$0",
num);
}
sdbus::ObjectPath advertisement_monitor_path(absl::string_view uuid) {
return absl::Substitute(
"/com/google/nearby/medium/ble/advertisement/monitor/$0",
absl::StrReplaceAll(uuid, {{"-", "_"}}));
}
int16_t TxPowerLevelDbm(api::ble_v2::TxPowerLevel level) {
switch (level) {
case api::ble_v2::TxPowerLevel::kUnknown:
return 0;
case api::ble_v2::TxPowerLevel::kUltraLow:
return -3;
case api::ble_v2::TxPowerLevel::kLow:
return 0;
case api::ble_v2::TxPowerLevel::kMedium:
return 3;
case api::ble_v2::TxPowerLevel::kHigh:
return 6;
}
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -20,8 +20,6 @@
#include <sdbus-c++/Types.h>
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/ble_v2.h"
#include <string>
#define BLUEZ_LOG_METHOD_CALL_ERROR(proxy, method, err) \
@@ -46,19 +44,10 @@ static constexpr const char *DEVICE_PROP_PAIRED = "Paired";
static constexpr const char *DEVICE_PROP_CONNECTED = "Connected";
static constexpr const char *DEVICE_NAME = "Name";
static constexpr const char *NEARBY_BLE_GATT_PATH_ROOT =
"/com/google/nearby/medium/ble/gatt";
std::string device_object_path(const sdbus::ObjectPath &adapter_object_path,
absl::string_view mac_address);
sdbus::ObjectPath profile_object_path(absl::string_view service_uuid);
sdbus::ObjectPath adapter_object_path(absl::string_view name);
sdbus::ObjectPath gatt_service_path(size_t num);
sdbus::ObjectPath gatt_characteristic_path(
const sdbus::ObjectPath &service_path, size_t num);
sdbus::ObjectPath ble_advertisement_path(size_t num);
sdbus::ObjectPath advertisement_monitor_path(absl::string_view uuid);
int16_t TxPowerLevelDbm(api::ble_v2::TxPowerLevel level);
class BluezObjectManager
: public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
@@ -1,68 +0,0 @@
#include "internal/platform/implementation/linux/bluez_advertisement_monitor.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/utils.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
namespace bluez {
AdvertisementMonitor::AdvertisementMonitor(
sdbus::IConnection &system_bus, Uuid service_uuid,
api::ble_v2::TxPowerLevel tx_power_level, absl::string_view type,
std::shared_ptr<BluetoothDevices> devices,
api::ble_v2::BleMedium::ScanCallback scan_callback)
: AdvertisementMonitor(
system_bus, service_uuid, tx_power_level, type, std::move(devices),
api::ble_v2::BleMedium::ScanningCallback{
.start_scanning_result = nullptr,
.advertisement_found_cb =
std::move(scan_callback.advertisement_found_cb)}) {}
AdvertisementMonitor::AdvertisementMonitor(
sdbus::IConnection &system_bus, Uuid service_uuid,
api::ble_v2::TxPowerLevel tx_power_level, absl::string_view type,
std::shared_ptr<BluetoothDevices> devices,
api::ble_v2::BleMedium::ScanningCallback scan_callback)
: AdaptorInterfaces(system_bus, bluez::advertisement_monitor_path(
std::string{service_uuid})),
devices_(std::move(devices)),
scan_callback_{std::move(scan_callback.advertisement_found_cb)},
start_scanning_result_callback_(
std::move(scan_callback.start_scanning_result)),
type_(type),
service_uuid_(service_uuid),
tx_power_level_(tx_power_level) {
registerAdaptor();
}
void AdvertisementMonitor::DeviceFound(const sdbus::ObjectPath &device) {
devices_->cleanup_lost_peripherals();
auto peripheral = devices_->add_new_device(device);
auto service_data = peripheral->ServiceData();
if (!service_data.has_value()) return;
struct api::ble_v2::BleAdvertisementData adv_data;
for (const auto &[uuid_str, data] : *service_data) {
auto uuid = UuidFromString(uuid_str);
if (!uuid.has_value()) {
LOG(ERROR)
<< __func__
<< ": Could not parse UUID string in ServiceData for peripheral "
<< peripheral->getObjectPath();
continue;
}
std::vector<uint8_t> bytes = data;
adv_data.service_data.emplace(*uuid,
std::string(bytes.begin(), bytes.end()));
}
scan_callback_.advertisement_found_cb(*peripheral, adv_data);
}
void AdvertisementMonitor::DeviceLost(const sdbus::ObjectPath &device) {
devices_->mark_peripheral_lost(device);
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,95 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_H_
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/StandardInterfaces.h>
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_server.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
namespace bluez {
class AdvertisementMonitor final
: public sdbus::AdaptorInterfaces<org::bluez::AdvertisementMonitor1_adaptor,
sdbus::ManagedObject_adaptor> {
public:
AdvertisementMonitor(const AdvertisementMonitor&) = delete;
AdvertisementMonitor(AdvertisementMonitor&&) = delete;
AdvertisementMonitor& operator=(const AdvertisementMonitor&) = delete;
AdvertisementMonitor& operator=(AdvertisementMonitor&&) = delete;
AdvertisementMonitor(sdbus::IConnection& system_bus, Uuid service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
absl::string_view type,
std::shared_ptr<BluetoothDevices> devices,
api::ble_v2::BleMedium::ScanCallback scan_callback);
AdvertisementMonitor(sdbus::IConnection& system_bus, Uuid service_uuid,
api::ble_v2::TxPowerLevel tx_power_level,
absl::string_view type,
std::shared_ptr<BluetoothDevices> devices,
api::ble_v2::BleMedium::ScanningCallback scan_callback);
~AdvertisementMonitor() { unregisterAdaptor(); }
private:
// Methods
void Release() override {}
void Activate() override {
if (start_scanning_result_callback_ != nullptr) {
start_scanning_result_callback_(absl::OkStatus());
}
}
void DeviceFound(const sdbus::ObjectPath& device) override;
void DeviceLost(const sdbus::ObjectPath& device) override;
// Properties
std::string Type() override { return type_; };
int16_t RSSILowThreshold() override { return 0; };
int16_t RSSIHighThreshold() override {
return bluez::TxPowerLevelDbm(tx_power_level_);
}
uint16_t RSSISamplingPeriod() override {
// The Windows implementation uses a sampling interval of 2 seconds.
return 20;
}
std::vector<sdbus::Struct<uint8_t, uint8_t, std::vector<uint8_t>>> Patterns()
override {
std::array<char, 16> service_id_data = service_uuid_.data();
return {{0,
0x16,
{static_cast<uint8_t>(service_id_data[3] & 0xFF),
static_cast<uint8_t>(service_id_data[2] & 0xFF)}}};
};
std::shared_ptr<BluetoothDevices> devices_;
api::ble_v2::BleMedium::ScanCallback scan_callback_;
absl::AnyInvocable<void(absl::Status)> start_scanning_result_callback_;
std::string type_;
Uuid service_uuid_;
api::ble_v2::TxPowerLevel tx_power_level_;
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,87 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_MANAGER_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_ADVERTISEMENT_MONITOR_MANAGER_H_
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/advertisement_monitor_manager_client.h"
namespace nearby {
namespace linux {
namespace bluez {
class AdvertisementMonitorManager final
: public sdbus::ProxyInterfaces<
org::bluez::AdvertisementMonitorManager1_proxy> {
private:
friend std::unique_ptr<AdvertisementMonitorManager>
std::make_unique<AdvertisementMonitorManager>(sdbus::IConnection &,
const BluetoothAdapter &);
AdvertisementMonitorManager(sdbus::IConnection &system_bus,
const BluetoothAdapter &adapter)
: ProxyInterfaces(system_bus, "org.bluez", adapter.GetObjectPath()) {
registerProxy();
}
public:
AdvertisementMonitorManager(const AdvertisementMonitorManager &) = delete;
AdvertisementMonitorManager(AdvertisementMonitorManager &&) = delete;
AdvertisementMonitorManager &operator=(const AdvertisementMonitorManager &) =
delete;
AdvertisementMonitorManager &operator=(AdvertisementMonitorManager &&) =
delete;
~AdvertisementMonitorManager() { unregisterProxy(); }
static std::unique_ptr<AdvertisementMonitorManager>
DiscoverAdvertisementMonitorManager(sdbus::IConnection &system_bus,
const BluetoothAdapter &adapter) {
bluez::BluezObjectManager manager(system_bus);
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = manager.GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(&manager, "GetManagedObjects", e);
return nullptr;
}
if (objects.count(adapter.GetObjectPath()) == 0) {
LOG(ERROR) << __func__ << ": Adapter object no longer exists "
<< adapter.GetObjectPath();
return nullptr;
}
if (objects[adapter.GetObjectPath()].count(
org::bluez::AdvertisementMonitorManager1_proxy::INTERFACE_NAME) ==
0) {
LOG(ERROR)
<< __func__ << ": Adapter " << adapter.GetObjectPath()
<< " doesn't provide "
<< org::bluez::AdvertisementMonitorManager1_proxy::INTERFACE_NAME;
return nullptr;
}
return std::make_unique<AdvertisementMonitorManager>(system_bus, adapter);
}
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -0,0 +1,119 @@
#include "bluez_agent.h"
#include <sdbus-c++/AdaptorInterfaces.h>
#include "generated/dbus/bluez/agentmanager_client.h"
#include "generated/dbus/bluez/agent_server.h"
#include "internal/platform/logging.h"
#include "internal/platform/implementation/linux/bluez.h"
namespace nearby
{
namespace linux
{
// org.bluez.Agent1 methods (BlueZ will call these)
void Agent::Release()
{
LOG(INFO) << "[agent] Release()\n";
}
std::string Agent::RequestPinCode(const sdbus::ObjectPath& device)
{
LOG(INFO) << "[agent] RequestPinCode(" << device << ")\n";
// If you truly have no UI, you may want to reject instead of guessing:
// throw sdbus::Error("org.bluez.Error.Rejected", "No PIN entry available");
return "0000";
}
void Agent::DisplayPinCode(const sdbus::ObjectPath& device, const std::string& pincode)
{
LOG(INFO) << "[agent] DisplayPinCode(" << device << ", " << pincode << ")\n";
}
uint32_t Agent::RequestPasskey(const sdbus::ObjectPath& device)
{
LOG(INFO) << "[agent] RequestPasskey(" << device << ")\n";
// Same idea: reject if you cannot securely provide a passkey
// throw sdbus::Error("org.bluez.Error.Rejected", "No passkey entry available");
return 123456;
}
void Agent::DisplayPasskey(const sdbus::ObjectPath& device, const uint32_t& passkey,
const uint16_t& entered)
{
LOG(INFO) << "[agent] DisplayPasskey(" << device << ", " << passkey
<< ", entered=" << entered << ")\n";
}
void Agent::RequestConfirmation(const sdbus::ObjectPath& device, const uint32_t& passkey)
{
LOG(INFO) << "[agent] RequestConfirmation(" << device << ", " << passkey << ") -> ACCEPT\n";
// Accept by returning normally.
// Reject with:
// throw sdbus::Error("org.bluez.Error.Rejected", "User rejected confirmation");
}
void Agent::RequestAuthorization(const sdbus::ObjectPath& device)
{
LOG(INFO) << "[agent] RequestAuthorization(" << device << ") -> ACCEPT\n";
}
void Agent::AuthorizeService(const sdbus::ObjectPath& device, const std::string& uuid)
{
LOG(INFO) << "[agent] AuthorizeService(" << device << ", " << uuid << ") -> ACCEPT\n";
// You can enforce allowlist here if you want.
}
void Agent::Cancel()
{
LOG(INFO) << "[agent] Cancel()\n";
}
bool AgentManager::AgentRegistered(absl::string_view agent_object_path) {
registered_agents_mutex_.ReaderLock();
bool registered =
registered_agents_.count(std::string(agent_object_path)) == 1;
registered_agents_mutex_.ReaderUnlock();
return registered;
}
bool AgentManager::Register(std::optional<absl::string_view> capability,
const sdbus::ObjectPath& agent_object_path) {
absl::MutexLock l(&registered_agents_mutex_);
const std::string agent_path_str = std::string(agent_object_path);
if (registered_agents_.count(agent_path_str) == 1) {
LOG(WARNING) << __func__ << ": Trying to register agent "
<< agent_path_str << " which was already registered.";
return true;
}
// Keep the agent alive by storing it.
auto agent = std::make_shared<Agent>(
getProxy().getConnection(),
sdbus::ObjectPath(agent_object_path));
try {
// BlueZ capability examples: "NoInputNoOutput", "DisplayYesNo", "KeyboardOnly", ...
const std::string cap =
capability.has_value() ? std::string(*capability) : "NoInputNoOutput";
// These are methods on org.bluez.AgentManager1_proxy (generated)
RegisterAgent(agent->getObjectPath(), cap);
RequestDefaultAgent(agent->getObjectPath());
} catch (const sdbus::Error& e) {
BLUEZ_LOG_METHOD_CALL_ERROR(&getProxy(), "RegisterAgent/RequestDefaultAgent", e);
return false;
}
registered_agents_.emplace(agent_path_str, agent);
LOG(INFO) << __func__ << ": Registered agent instance at path "
<< agent_path_str;
return true;
}
};
}
@@ -0,0 +1,90 @@
#pragma once
#include <cstdint>
#include <string>
#include <utility> // std::move
#include <sdbus-c++/sdbus-c++.h>
#include "generated/dbus/bluez/agentmanager_client.h"
#include "internal/platform/logging.h"
#include "generated/dbus/bluez/agent_server.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/bluez.h"
namespace nearby::linux
{
class Agent final : public sdbus::AdaptorInterfaces<org::bluez::Agent1_adaptor>
{
public:
Agent(const Agent&) = delete;
Agent(Agent&&) = delete;
Agent& operator=(const Agent&) = delete;
Agent& operator=(Agent&&) = delete;
Agent(sdbus::IConnection& system_bus, sdbus::ObjectPath path)
: AdaptorInterfaces(system_bus, std::move(path))
{
registerAdaptor();
LOG(INFO) << "Created new Agent at path: " << getObjectPath();
}
~Agent()
{
unregisterAdaptor();
}
private:
// org.bluez.Agent1 methods (BlueZ will call these)
void Release() override;
std::string RequestPinCode(const sdbus::ObjectPath& device) override;
void DisplayPinCode(const sdbus::ObjectPath& device,
const std::string& pincode) override;
uint32_t RequestPasskey(const sdbus::ObjectPath& device) override;
void DisplayPasskey(const sdbus::ObjectPath& device,
const uint32_t& passkey,
const uint16_t& entered) override;
void RequestConfirmation(const sdbus::ObjectPath& device,
const uint32_t& passkey) override;
void RequestAuthorization(const sdbus::ObjectPath& device) override;
void AuthorizeService(const sdbus::ObjectPath& device,
const std::string& uuid) override;
void Cancel() override;
};
class AgentManager final
: public sdbus::ProxyInterfaces<org::bluez::AgentManager1_proxy>
{
public:
AgentManager(const AgentManager&) = delete;
AgentManager(AgentManager&&) = delete;
AgentManager& operator=(const AgentManager&) = delete;
AgentManager& operator=(AgentManager&&) = delete;
explicit AgentManager(sdbus::IConnection& system_bus)
: ProxyInterfaces(system_bus, bluez::SERVICE_DEST, "/org/bluez")
{
registerProxy();
}
~AgentManager() { unregisterProxy(); }
bool Register(std::optional<absl::string_view> capability,
const sdbus::ObjectPath& agent_object_path);
// In AgentManager class declaration:
bool AgentRegistered(absl::string_view agent_object_path);
private:
absl::Mutex registered_agents_mutex_;
std::map<std::string, std::shared_ptr<Agent>> registered_agents_
ABSL_GUARDED_BY(registered_agents_mutex_);
};
} // namespace nearby::linux
@@ -1,41 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>
#include <string>
#include <vector>
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_client.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_client.h"
namespace nearby {
namespace linux {
namespace bluez {
void SubscribedGattCharacteristicClient::onPropertiesChanged(
const std::string& interfaceName,
const std::map<std::string, sdbus::Variant>& changedProperties,
const std::vector<std::string>& invalidatedProperties) {
if (interfaceName != org::bluez::GattCharacteristic1_proxy::INTERFACE_NAME)
return;
if (changedProperties.count("Value") == 1) {
std::vector<uint8_t> value_bytes = changedProperties.at("Value");
if (notify_callback_ != nullptr) {
auto value = std::string(value_bytes.cbegin(), value_bytes.cend());
notify_callback_(value);
}
}
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,71 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_CLIENT_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_CLIENT_H_
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_client.h"
namespace nearby {
namespace linux {
namespace bluez {
class GattCharacteristicClient
: public sdbus::ProxyInterfaces<org::bluez::GattCharacteristic1_proxy,
sdbus::Properties_proxy> {
public:
GattCharacteristicClient(std::shared_ptr<sdbus::IConnection> system_bus,
sdbus::ObjectPath path)
: ProxyInterfaces(*system_bus, "org.bluez", std::move(path)),
system_bus_(std::move(system_bus)) {
registerProxy();
}
virtual ~GattCharacteristicClient() { unregisterProxy(); }
protected:
void onPropertiesChanged(
const std::string& interfaceName,
const std::map<std::string, sdbus::Variant>& changedProperties,
const std::vector<std::string>& invalidatedProperties) override {}
std::shared_ptr<sdbus::IConnection> system_bus_;
};
class SubscribedGattCharacteristicClient : public GattCharacteristicClient {
public:
SubscribedGattCharacteristicClient(
std::shared_ptr<sdbus::IConnection> system_bus, sdbus::ObjectPath path,
absl::AnyInvocable<void(absl::string_view value)> notify_callback)
: GattCharacteristicClient(std::move(system_bus), std::move(path)),
notify_callback_(std::move(notify_callback)) {}
protected:
void onPropertiesChanged(
const std::string& interfaceName,
const std::map<std::string, sdbus::Variant>& changedProperties,
const std::vector<std::string>& invalidatedProperties) override;
private:
absl::AnyInvocable<void(absl::string_view value)> notify_callback_;
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,238 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdbus-c++/Error.h>
#include <sdbus-c++/MethodResult.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_server.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
namespace bluez {
void GattCharacteristicServer::Update(const nearby::ByteArray &value) {
std::vector<uint8_t> bytes(value.size());
const auto *buf = value.data();
for (auto i = 0; i < value.size(); i++) bytes[i] = buf[i];
absl::MutexLock static_value_lock(&static_value_mutex_);
static_value_ = std::move(bytes);
}
absl::Status GattCharacteristicServer::NotifyChanged(
bool confirm, const ByteArray &new_value) {
std::vector<uint8_t> bytes(new_value.size());
const auto *buf = new_value.data();
for (auto i = 0; i < new_value.size(); i++) bytes[i] = buf[i];
{
absl::MutexLock lock(&cached_value_mutex_);
cached_value_ = bytes;
}
if (confirm) {
auto confirmed = [&]() {
confirmed_mutex_.AssertReaderHeld();
return confirmed_;
};
{
absl::MutexLock lock(&confirmed_mutex_);
confirmed_ = false;
}
absl::ReaderMutexLock lock(&confirmed_mutex_, absl::Condition(&confirmed));
}
try {
emitPropertiesChangedSignal(GattCharacteristic1_adaptor::INTERFACE_NAME,
{"Value"});
return absl::OkStatus();
} catch (const sdbus::Error &e) {
LOG(ERROR) << __func__
<< ": Error emitting PropertiesChanged signal on "
<< getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
return absl::UnknownError(e.getMessage());
}
}
void GattCharacteristicServer::ReadValue(
sdbus::Result<std::vector<uint8_t>> &&result,
std::map<std::string, sdbus::Variant> options) {
{
absl::ReaderMutexLock static_value_lock(&static_value_mutex_);
if (static_value_.has_value()) {
result.returnResults(*static_value_);
absl::MutexLock cached_value_lock(&cached_value_mutex_);
cached_value_ = *static_value_;
return;
}
}
uint16_t offset = options["offset"];
sdbus::ObjectPath device_path = options["device"];
auto device = devices_->get_device_by_path(device_path);
if (device == nullptr) {
result.returnError(
sdbus::Error("org.bluez.Error.NotAuthorized", "device does not exist"));
return;
}
auto characteristic = characteristic_;
server_cb_->on_characteristic_read_cb(
*device, characteristic, static_cast<int>(offset),
[result = std::move(result),
this](absl::StatusOr<absl::string_view> data) {
const auto &status = data.status();
if (status.ok()) {
auto str = data.value();
std::vector<uint8_t> bytes(str.size());
for (auto i = 0; i < str.size(); i++) {
bytes[i] = str[i];
}
result.returnResults(bytes);
absl::MutexLock lock(&cached_value_mutex_);
cached_value_ = bytes;
} else if (absl::IsPermissionDenied(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotPermitted",
std::string(status.message())));
} else if (absl::IsUnauthenticated(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotAuthorized",
std::string(status.message())));
} else if (absl::IsOutOfRange(status)) {
result.returnError(sdbus::Error("org.bluez.Error.InvalidOffset",
std::string(status.message())));
} else if (absl::IsUnimplemented(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotSupported",
std::string(status.message())));
} else {
result.returnError(sdbus::Error("org.bluez.Error.Failed",
std::string(status.message())));
}
});
}
void GattCharacteristicServer::WriteValue(
sdbus::Result<> &&result, std::vector<uint8_t> value,
std::map<std::string, sdbus::Variant> options) {
uint16_t offset = options["offset"];
sdbus::ObjectPath device_path = options["device"];
auto device = devices_->get_device_by_path(device_path);
if (device == nullptr) {
result.returnError(
sdbus::Error("org.bluez.Error.NotAuthorized", "device does not exist"));
return;
}
std::string type = options["type"];
std::string data(value.begin(), value.end());
auto characteristic = characteristic_;
// TODO: Support writes without response.
server_cb_->on_characteristic_write_cb(
*device, characteristic, static_cast<int>(offset), data,
[result = std::move(result)](absl::Status status) {
if (status.ok()) {
result.returnResults();
} else if (absl::IsPermissionDenied(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotPermitted",
std::string(status.message())));
} else if (absl::IsUnauthenticated(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotAuthorized",
std::string(status.message())));
} else if (absl::IsOutOfRange(status)) {
result.returnError(sdbus::Error("org.bluez.Error.InvalidOffset",
std::string(status.message())));
} else if (absl::IsUnimplemented(status)) {
result.returnError(sdbus::Error("org.bluez.Error.NotSupported",
std::string(status.message())));
} else {
result.returnError(sdbus::Error("org.bluez.Error.Failed",
std::string(status.message())));
}
});
}
void GattCharacteristicServer::StartNotify() {
if ((characteristic_.property |
api::ble_v2::GattCharacteristic::Property::kNotify) ==
api::ble_v2::GattCharacteristic::Property::kNotify) {
if (notify_sessions_.fetch_add(1) == 0) {
if (server_cb_->characteristic_subscription_cb != nullptr) {
server_cb_->characteristic_subscription_cb(characteristic_);
}
notifying_ = true;
}
} else {
throw(sdbus::Error("org.bluez.Error.NotSupported"));
}
}
void GattCharacteristicServer::StopNotify() {
if ((characteristic_.property |
api::ble_v2::GattCharacteristic::Property::kNotify) ==
api::ble_v2::GattCharacteristic::Property::kNotify) {
if (notify_sessions_.fetch_sub(0) == 1) {
if (server_cb_->characteristic_unsubscription_cb != nullptr) {
server_cb_->characteristic_unsubscription_cb(characteristic_);
}
notifying_ = false;
}
} else {
throw(sdbus::Error("org.bluez.Error.Failed"));
}
}
std::vector<std::string> GattCharacteristicServer::Flags() {
auto characteristic = characteristic_;
std::vector<std::string> flags;
if ((characteristic.permission &
api::ble_v2::GattCharacteristic::Permission::kRead) ==
api::ble_v2::GattCharacteristic::Permission::kRead ||
(characteristic.property &
api::ble_v2::GattCharacteristic::Property::kRead) ==
api::ble_v2::GattCharacteristic::Property::kRead)
flags.push_back("read");
if ((characteristic.permission &
api::ble_v2::GattCharacteristic::Permission::kWrite) ==
api::ble_v2::GattCharacteristic::Permission::kWrite ||
(characteristic.property &
api::ble_v2::GattCharacteristic::Property::kWrite) ==
api::ble_v2::GattCharacteristic::Property::kWrite) {
flags.push_back("write");
flags.push_back("write-without-response");
}
if ((characteristic.property &
api::ble_v2::GattCharacteristic::Property::kIndicate) ==
api::ble_v2::GattCharacteristic::Property::kIndicate)
flags.push_back("indicate");
if ((characteristic.property &
api::ble_v2::GattCharacteristic::Property::kNotify) ==
api::ble_v2::GattCharacteristic::Property::kNotify)
flags.push_back("notify");
return flags;
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,129 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_SERVER_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_CHARACTERISTIC_SERVER_H_
#include <atomic>
#include <map>
#include <optional>
#include <string>
#include <vector>
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/MethodResult.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluetooth_devices.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
namespace bluez {
class GattCharacteristicServer final
: public sdbus::AdaptorInterfaces<org::bluez::GattCharacteristic1_adaptor,
sdbus::Properties_adaptor,
sdbus::ManagedObject_adaptor> {
public:
GattCharacteristicServer(const GattCharacteristicServer &) = delete;
GattCharacteristicServer(GattCharacteristicServer &&) = delete;
GattCharacteristicServer &operator=(const GattCharacteristicServer &) =
delete;
GattCharacteristicServer &operator=(GattCharacteristicServer &&) = delete;
GattCharacteristicServer(
sdbus::IConnection &system_bus,
const sdbus::ObjectPath &service_object_path, size_t num,
const api::ble_v2::GattCharacteristic &characteristic,
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb,
std::shared_ptr<BluetoothDevices> devices)
: AdaptorInterfaces(system_bus, bluez::gatt_characteristic_path(
service_object_path, num)),
devices_(std::move(devices)),
server_cb_(std::move(server_cb)),
characteristic_(characteristic),
service_object_path_(service_object_path),
notifying_(false),
confirmed_(false),
notify_sessions_(0) {
registerAdaptor();
LOG(INFO)
<< __func__ << "Creating a "
<< org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME
<< " object at " << getObjectPath();
}
~GattCharacteristicServer() { unregisterAdaptor(); }
void Update(const nearby::ByteArray &value)
ABSL_LOCKS_EXCLUDED(static_value_mutex_);
absl::Status NotifyChanged(bool confirm, const ByteArray &new_value)
ABSL_LOCKS_EXCLUDED(confirmed_mutex_);
private:
// Methods
void ReadValue(sdbus::Result<std::vector<uint8_t>> &&result,
std::map<std::string, sdbus::Variant> options) override
ABSL_LOCKS_EXCLUDED(cached_value_mutex_, static_value_mutex_);
void WriteValue(sdbus::Result<> &&result, std::vector<uint8_t> value,
std::map<std::string, sdbus::Variant> options) override;
void StartNotify() override;
void StopNotify() override;
void Confirm() override ABSL_LOCKS_EXCLUDED(confirmed_mutex_) {
absl::MutexLock lock(&confirmed_mutex_);
confirmed_ = true;
};
// Properties
std::string UUID() override { return std::string{characteristic_.uuid}; }
sdbus::ObjectPath Service() override { return service_object_path_; }
bool Notifying() override { return notifying_; }
std::vector<std::string> Flags() override;
std::vector<uint8_t> Value() override
ABSL_LOCKS_EXCLUDED(cached_value_mutex_) {
absl::ReaderMutexLock lock(&cached_value_mutex_);
return cached_value_;
}
std::shared_ptr<BluetoothDevices> devices_;
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
api::ble_v2::GattCharacteristic characteristic_;
// Set by `GattServer::UpdateCharacteristic()`
absl::Mutex static_value_mutex_;
std::optional<std::vector<uint8_t>> static_value_
ABSL_GUARDED_BY(static_value_mutex_);
sdbus::ObjectPath service_object_path_;
std::atomic_bool notifying_;
absl::Mutex cached_value_mutex_;
std::vector<uint8_t> cached_value_ ABSL_GUARDED_BY(cached_value_mutex_);
absl::Mutex confirmed_mutex_;
bool confirmed_;
std::atomic_size_t notify_sessions_;
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,44 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
#define PLATFORM_IMPL_LINUX_API_BLUEZ_GATT_MANAGER_H_
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_manager_client.h"
namespace nearby {
namespace linux {
namespace bluez {
class GattManager
: public sdbus::ProxyInterfaces<org::bluez::GattManager1_proxy> {
public:
GattManager(const GattManager &) = delete;
GattManager(GattManager &&) = delete;
GattManager &operator=(const GattManager &) = delete;
GattManager &operator=(GattManager &&) = delete;
GattManager(sdbus::IConnection &system_bus,
sdbus::ObjectPath adapter_object_path)
: ProxyInterfaces(system_bus, "org.bluez",
std::move(adapter_object_path)) {
registerProxy();
}
~GattManager() { unregisterProxy(); }
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,40 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_CLIENT_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_CLIENT_H_
#include <memory>
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_client.h"
namespace nearby {
namespace linux {
class GattServiceClient final
: public sdbus::ProxyInterfaces<org::bluez::GattService1_proxy> {
public:
GattServiceClient(std::shared_ptr<sdbus::IConnection> system_bus,
sdbus::ObjectPath service_object_path)
: ProxyInterfaces(*system_bus, "org.bluez",
std::move(service_object_path)) {
registerProxy();
}
~GattServiceClient() { unregisterProxy(); }
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,63 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "internal/platform/implementation/linux/bluez_gatt_service_server.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_server.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
namespace bluez {
bool GattServiceServer::AddCharacteristic(
const Uuid &service_uuid, const Uuid &characteristic_uuid,
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property) {
absl::MutexLock lock(&characterstics_mutex_);
api::ble_v2::GattCharacteristic characteristic{
characteristic_uuid, service_uuid, permission, property};
auto count = characteristics_.size();
std::shared_ptr<GattCharacteristicServer> chr =
std::make_shared<GattCharacteristicServer>(
getObject().getConnection(), getObjectPath(), count, characteristic,
server_cb_, devices_);
try {
chr->emitInterfacesAddedSignal(
{org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesAdded signal for object path "
<< chr->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
return false;
}
characteristics_.insert({characteristic_uuid, std::move(chr)});
return true;
}
std::shared_ptr<GattCharacteristicServer> GattServiceServer::GetCharacteristic(
const Uuid &uuid) {
absl::ReaderMutexLock lock(&characterstics_mutex_);
if (characteristics_.count(uuid) == 0) {
return nullptr;
}
return characteristics_[uuid];
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,110 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_H_
#define PLATFORM_IMPL_LINUX_BLUEZ_GATT_SERVICE_H_
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_gatt_characteristic_server.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_characteristic_server.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/gatt_service_server.h"
#include "internal/platform/logging.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
namespace bluez {
class GattServiceServer final
: public sdbus::AdaptorInterfaces<org::bluez::GattService1_adaptor,
sdbus::ManagedObject_adaptor,
sdbus::Properties_adaptor> {
public:
GattServiceServer(const GattServiceServer &) = delete;
GattServiceServer(GattServiceServer &&) = delete;
GattServiceServer &operator=(const GattServiceServer &) = delete;
GattServiceServer &operator=(GattServiceServer &&) = delete;
GattServiceServer(
sdbus::IConnection &system_bus, size_t num, const Uuid &service_uuid,
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb,
std::shared_ptr<BluetoothDevices> devices)
: AdaptorInterfaces(system_bus, bluez::gatt_service_path(num)),
devices_(std::move(devices)),
server_cb_(std::move(server_cb)),
uuid_(service_uuid),
primary_(true) {
registerAdaptor();
LOG(INFO) << __func__ << ": Created a "
<< org::bluez::GattService1_adaptor::INTERFACE_NAME
<< " object at " << getObjectPath();
}
~GattServiceServer() {
absl::MutexLock lock(&characterstics_mutex_);
for (auto &[_uuid, characteristic] : characteristics_) {
LOG(INFO) << __func__ << ": Removing characteristic "
<< characteristic->getObjectPath();
try {
characteristic->emitInterfacesRemovedSignal(
{org::bluez::GattCharacteristic1_adaptor::INTERFACE_NAME});
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__
<< ": error emitting InterfacesRemoved signal for object path "
<< characteristic->getObjectPath() << " with name '" << e.getName()
<< "' and message '" << e.getMessage() << "'";
}
}
unregisterAdaptor();
}
bool AddCharacteristic(const Uuid &service_uuid,
const Uuid &characteristic_uuid,
api::ble_v2::GattCharacteristic::Permission permission,
api::ble_v2::GattCharacteristic::Property property)
ABSL_LOCKS_EXCLUDED(characterstics_mutex_);
std::shared_ptr<GattCharacteristicServer> GetCharacteristic(const Uuid &uuid)
ABSL_LOCKS_EXCLUDED(characterstics_mutex_);
private:
// Properties
std::string UUID() override { return uuid_; }
bool Primary() override { return primary_; }
sdbus::ObjectPath Device() override { return "/"; }
std::vector<sdbus::ObjectPath> Includes() override { return {}; }
absl::Mutex characterstics_mutex_;
absl::flat_hash_map<Uuid, std::shared_ptr<GattCharacteristicServer>>
characteristics_ ABSL_GUARDED_BY(characterstics_mutex_);
std::shared_ptr<BluetoothDevices> devices_;
std::shared_ptr<api::ble_v2::ServerGattConnectionCallback> server_cb_;
const std::string uuid_;
const bool primary_;
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -1,54 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <vector>
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/bluez_le_advertisement.h"
#include "internal/platform/logging.h"
#include "internal/platform/uuid.h"
namespace nearby {
namespace linux {
namespace bluez {
LEAdvertisement::LEAdvertisement(
sdbus::IConnection& system_bus, sdbus::ObjectPath path,
const api::ble_v2::BleAdvertisementData& advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters)
: AdaptorInterfaces(system_bus, std::move(path)),
is_extended_advertisement_(advertising_data.is_extended_advertisement),
advertise_set_parameters_(advertise_set_parameters) {
for (const auto& [uuid, data] : advertising_data.service_data) {
std::string uuid_string(uuid);
std::vector<uint8_t> data_bytes(data.size());
const auto* bytes = data.data();
service_uuids_.push_back(uuid_string);
for (size_t i = 0; i < data.size(); i++) {
data_bytes[i] = bytes[i];
}
service_data_.insert({uuid_string, std::move(data_bytes)});
}
registerAdaptor();
LOG(INFO) << __func__
<< ": Created a org.bluez.LEAdvertisement1 instance at "
<< getObjectPath();
}
} // namespace bluez
} // namespace linux
} // namespace nearby
@@ -1,112 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_API_BLUEZ_BLE_ADVERTISEMENT_H_
#define PLATFORM_IMPL_LINUX_API_BLUEZ_BLE_ADVERTISEMENT_H_
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "internal/platform/implementation/linux/bluez.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_manager_client.h"
#include "internal/platform/implementation/linux/generated/dbus/bluez/le_advertisement_server.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
namespace bluez {
class LEAdvertisement final
: public sdbus::AdaptorInterfaces<org::bluez::LEAdvertisement1_adaptor,
sdbus::ObjectManager_adaptor> {
public:
LEAdvertisement(const LEAdvertisement&) = delete;
LEAdvertisement(LEAdvertisement&&) = delete;
LEAdvertisement& operator=(const LEAdvertisement&) = delete;
LEAdvertisement& operator=(LEAdvertisement&&) = delete;
LEAdvertisement(sdbus::IConnection& system_bus, sdbus::ObjectPath path,
const api::ble_v2::BleAdvertisementData& advertising_data,
api::ble_v2::AdvertiseParameters advertise_set_parameters);
static std::unique_ptr<LEAdvertisement> CreateLEAdvertisement(
sdbus::IConnection& system_bus,
const api::ble_v2::BleAdvertisementData& advertising_data,
api::ble_v2::AdvertiseParameters advertising_parameters) {
static std::atomic<size_t> adv_count = 0;
auto object_path = bluez::ble_advertisement_path(adv_count++);
return std::make_unique<LEAdvertisement>(
system_bus, object_path, advertising_data, advertising_parameters);
}
~LEAdvertisement() { unregisterAdaptor(); }
private:
// Methods
void Release() override {
LOG(INFO) << __func__
<< ": LE Advertisement released: " << getObjectPath();
}
// Properties
std::string Type() override { return "peripheral"; }
std::vector<std::string> ServiceUUIDs() override { return service_uuids_; }
std::map<std::string, sdbus::Variant> ManufacturerData() override {
return {};
}
std::vector<std::string> SolicitUUIDs() override { return {}; }
std::map<std::string, sdbus::Variant> ServiceData() override {
return service_data_;
}
std::vector<std::string> Includes() override { return {}; }
std::string LocalName() override { return {}; }
uint16_t Duration() override { return 0; }
uint16_t Timeout() override { return 0; }
// Windows seems to hardcode the scan interval to 118.125 milliseconds, so
// lets just replicate that.
uint32_t MinInterval() override { return 118; }
uint32_t MaxInterval() override { return 119; }
int16_t TxPower() override {
return bluez::TxPowerLevelDbm(advertise_set_parameters_.tx_power_level);
};
bool is_extended_advertisement_;
std::vector<std::string> service_uuids_;
std::map<std::string, sdbus::Variant> service_data_;
api::ble_v2::AdvertiseParameters advertise_set_parameters_;
};
class LEAdvertisementManager final
: public sdbus::ProxyInterfaces<org::bluez::LEAdvertisingManager1_proxy> {
public:
LEAdvertisementManager(sdbus::IConnection& system_bus,
BluetoothAdapter& adapter)
: ProxyInterfaces(system_bus, "org.bluez", adapter.GetObjectPath()) {
registerProxy();
}
~LEAdvertisementManager() { unregisterProxy(); }
LEAdvertisementManager(const LEAdvertisementManager&) = delete;
LEAdvertisementManager(LEAdvertisementManager&&) = delete;
LEAdvertisementManager& operator=(const LEAdvertisementManager&) = delete;
LEAdvertisementManager& operator=(LEAdvertisementManager&&) = delete;
};
} // namespace bluez
} // namespace linux
} // namespace nearby
#endif
@@ -24,7 +24,6 @@
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/device_info.h"
#include "internal/platform/implementation/linux/avahi.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/device_info.h"
#include "internal/platform/logging.h"
@@ -64,11 +63,11 @@ DeviceInfo::DeviceInfo(std::shared_ptr<sdbus::IConnection> system_bus)
login_manager_(std::make_unique<LoginManager>(*system_bus_)) {}
std::optional<std::string> DeviceInfo::GetOsDeviceName() const {
avahi::Server avahi(*system_bus_);
Hostnamed hostnamed(*system_bus_);
try {
return avahi.GetHostNameFqdn();
return hostnamed.Hostname();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&avahi, "GetHostNameFqdn", e);
DBUS_LOG_PROPERTY_GET_ERROR(&hostnamed, "Hostname", e);
return std::nullopt;
}
}
@@ -1,94 +0,0 @@
/*
* 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 <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
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<std::vector<uint8_t>>& 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<std::vector<uint8_t>>& 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<uint8_t>& rdata)
{
proxy_.callMethod("AddRecord").onInterface(INTERFACE_NAME).withArguments(interface, protocol, flags, name, clazz, type, ttl, rdata);
}
private:
sdbus::IProxy& proxy_;
};
}}} // namespaces
#endif
@@ -1,94 +0,0 @@
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="introspect.xsl"?>
<!DOCTYPE node SYSTEM "introspect.dtd">
<!--
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
-->
<node>
<interface name="org.freedesktop.Avahi.EntryGroup">
<method name="Free"/>
<method name="Commit"/>
<method name="Reset"/>
<method name="GetState">
<arg name="state" type="i" direction="out"/>
</method>
<signal name="StateChanged">
<arg name="state" type="i"/>
<arg name="error" type="s"/>
</signal>
<method name="IsEmpty">
<arg name="empty" type="b" direction="out"/>
</method>
<method name="AddService">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="host" type="s" direction="in"/>
<arg name="port" type="q" direction="in"/>
<arg name="txt" type="aay" direction="in"/>
</method>
<method name="AddServiceSubtype">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="subtype" type="s" direction="in"/>
</method>
<method name="UpdateServiceTxt">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="txt" type="aay" direction="in"/>
</method>
<method name="AddAddress">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="address" type="s" direction="in"/>
</method>
<method name="AddRecord">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="clazz" type="q" direction="in"/>
<arg name="type" type="q" direction="in"/>
<arg name="ttl" type="u" direction="in"/>
<arg name="rdata" type="ay" direction="in"/>
</method>
</interface>
</node>
@@ -1,398 +0,0 @@
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="introspect.xsl"?>
<!DOCTYPE node SYSTEM "introspect.dtd">
<!--
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
-->
<node>
<interface name="org.freedesktop.Avahi.Server">
<method name="GetVersionString">
<arg name="version" type="s" direction="out"/>
</method>
<method name="GetAPIVersion">
<arg name="version" type="u" direction="out"/>
</method>
<method name="GetHostName">
<arg name="name" type="s" direction="out"/>
</method>
<method name="SetHostName">
<arg name="name" type="s" direction="in"/>
</method>
<method name="GetHostNameFqdn">
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetDomainName">
<arg name="name" type="s" direction="out"/>
</method>
<method name="IsNSSSupportAvailable">
<arg name="yes" type="b" direction="out"/>
</method>
<method name="GetState">
<arg name="state" type="i" direction="out"/>
</method>
<signal name="StateChanged">
<arg name="state" type="i"/>
<arg name="error" type="s"/>
</signal>
<method name="GetLocalServiceCookie">
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="GetAlternativeHostName">
<arg name="name" type="s" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetAlternativeServiceName">
<arg name="name" type="s" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetNetworkInterfaceNameByIndex">
<arg name="index" type="i" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetNetworkInterfaceIndexByName">
<arg name="name" type="s" direction="in"/>
<arg name="index" type="i" direction="out"/>
</method>
<method name="ResolveHostName">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="ResolveAddress">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="address" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="ResolveService">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="type" type="s" direction="out"/>
<arg name="domain" type="s" direction="out"/>
<arg name="host" type="s" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="port" type="q" direction="out"/>
<arg name="txt" type="aay" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="EntryGroupNew">
<arg name="path" type="o" direction="out"/>
</method>
<method name="DomainBrowserNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="btype" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceTypeBrowserNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceBrowserNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceResolverNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="HostNameResolverNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="AddressResolverNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="address" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="RecordBrowserNew">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="clazz" type="q" direction="in"/>
<arg name="type" type="q" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
</interface>
<interface name="org.freedesktop.Avahi.Server2">
<method name="GetVersionString">
<arg name="version" type="s" direction="out"/>
</method>
<method name="GetAPIVersion">
<arg name="version" type="u" direction="out"/>
</method>
<method name="GetHostName">
<arg name="name" type="s" direction="out"/>
</method>
<method name="SetHostName">
<arg name="name" type="s" direction="in"/>
</method>
<method name="GetHostNameFqdn">
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetDomainName">
<arg name="name" type="s" direction="out"/>
</method>
<method name="IsNSSSupportAvailable">
<arg name="yes" type="b" direction="out"/>
</method>
<method name="GetState">
<arg name="state" type="i" direction="out"/>
</method>
<signal name="StateChanged">
<arg name="state" type="i"/>
<arg name="error" type="s"/>
</signal>
<method name="GetLocalServiceCookie">
<arg name="cookie" type="u" direction="out"/>
</method>
<method name="GetAlternativeHostName">
<arg name="name" type="s" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetAlternativeServiceName">
<arg name="name" type="s" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetNetworkInterfaceNameByIndex">
<arg name="index" type="i" direction="in"/>
<arg name="name" type="s" direction="out"/>
</method>
<method name="GetNetworkInterfaceIndexByName">
<arg name="name" type="s" direction="in"/>
<arg name="index" type="i" direction="out"/>
</method>
<method name="ResolveHostName">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="ResolveAddress">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="address" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="ResolveService">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="type" type="s" direction="out"/>
<arg name="domain" type="s" direction="out"/>
<arg name="host" type="s" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="port" type="q" direction="out"/>
<arg name="txt" type="aay" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</method>
<method name="EntryGroupNew">
<arg name="path" type="o" direction="out"/>
</method>
<method name="DomainBrowserPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="btype" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceTypeBrowserPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceBrowserPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="ServiceResolverPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="type" type="s" direction="in"/>
<arg name="domain" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="HostNameResolverPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="aprotocol" type="i" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="AddressResolverPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="address" type="s" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
<method name="RecordBrowserPrepare">
<arg name="interface" type="i" direction="in"/>
<arg name="protocol" type="i" direction="in"/>
<arg name="name" type="s" direction="in"/>
<arg name="clazz" type="q" direction="in"/>
<arg name="type" type="q" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="path" type="o" direction="out"/>
</method>
</interface>
</node>
@@ -1,58 +0,0 @@
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="introspect.xsl"?>
<!DOCTYPE node SYSTEM "introspect.dtd">
<!--
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
-->
<node>
<interface name="org.freedesktop.Avahi.ServiceBrowser">
<method name="Free"/>
<method name="Start"/>
<signal name="ItemNew">
<arg name="interface" type="i"/>
<arg name="protocol" type="i"/>
<arg name="name" type="s"/>
<arg name="type" type="s"/>
<arg name="domain" type="s"/>
<arg name="flags" type="u"/>
</signal>
<signal name="ItemRemove">
<arg name="interface" type="i"/>
<arg name="protocol" type="i"/>
<arg name="name" type="s"/>
<arg name="type" type="s"/>
<arg name="domain" type="s"/>
<arg name="flags" type="u"/>
</signal>
<signal name="Failure">
<arg name="error" type="s"/>
</signal>
<signal name="AllForNow"/>
<signal name="CacheExhausted"/>
</interface>
</node>
@@ -1,57 +0,0 @@
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="introspect.xsl"?>
<!DOCTYPE node SYSTEM "introspect.dtd">
<!--
This file is part of avahi.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.
-->
<node>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg name="data" type="s" direction="out" />
</method>
</interface>
<interface name="org.freedesktop.Avahi.ServiceResolver">
<method name="Free"/>
<method name="Start"/>
<signal name="Found">
<arg name="interface" type="i" direction="out"/>
<arg name="protocol" type="i" direction="out"/>
<arg name="name" type="s" direction="out"/>
<arg name="type" type="s" direction="out"/>
<arg name="domain" type="s" direction="out"/>
<arg name="host" type="s" direction="out"/>
<arg name="aprotocol" type="i" direction="out"/>
<arg name="address" type="s" direction="out"/>
<arg name="port" type="q" direction="out"/>
<arg name="txt" type="aay" direction="out"/>
<arg name="flags" type="u" direction="out"/>
</signal>
<signal name="Failure">
<arg name="error" type="s"/>
</signal>
</interface>
</node>
@@ -1,399 +0,0 @@
/*
* 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 <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
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<int32_t, int32_t, std::string, int32_t, std::string, uint32_t> ResolveHostName(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags)
{
std::tuple<int32_t, int32_t, std::string, int32_t, std::string, uint32_t> result;
proxy_.callMethod("ResolveHostName").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result);
return result;
}
std::tuple<int32_t, int32_t, int32_t, std::string, std::string, uint32_t> ResolveAddress(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags)
{
std::tuple<int32_t, int32_t, int32_t, std::string, std::string, uint32_t> result;
proxy_.callMethod("ResolveAddress").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result);
return result;
}
std::tuple<int32_t, int32_t, std::string, std::string, std::string, std::string, int32_t, std::string, uint16_t, std::vector<std::vector<uint8_t>>, 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<int32_t, int32_t, std::string, std::string, std::string, std::string, int32_t, std::string, uint16_t, std::vector<std::vector<uint8_t>>, 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<int32_t, int32_t, std::string, int32_t, std::string, uint32_t> ResolveHostName(const int32_t& interface, const int32_t& protocol, const std::string& name, const int32_t& aprotocol, const uint32_t& flags)
{
std::tuple<int32_t, int32_t, std::string, int32_t, std::string, uint32_t> result;
proxy_.callMethod("ResolveHostName").onInterface(INTERFACE_NAME).withArguments(interface, protocol, name, aprotocol, flags).storeResultsTo(result);
return result;
}
std::tuple<int32_t, int32_t, int32_t, std::string, std::string, uint32_t> ResolveAddress(const int32_t& interface, const int32_t& protocol, const std::string& address, const uint32_t& flags)
{
std::tuple<int32_t, int32_t, int32_t, std::string, std::string, uint32_t> result;
proxy_.callMethod("ResolveAddress").onInterface(INTERFACE_NAME).withArguments(interface, protocol, address, flags).storeResultsTo(result);
return result;
}
std::tuple<int32_t, int32_t, std::string, std::string, std::string, std::string, int32_t, std::string, uint16_t, std::vector<std::vector<uint8_t>>, 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<int32_t, int32_t, std::string, std::string, std::string, std::string, int32_t, std::string, uint16_t, std::vector<std::vector<uint8_t>>, 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
@@ -1,58 +0,0 @@
/*
* 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 <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
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
@@ -1,57 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__advertisement_monitor_manager_client_h__proxy__H__
#define __sdbuscpp__advertisement_monitor_manager_client_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class AdvertisementMonitorManager1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.AdvertisementMonitorManager1";
protected:
AdvertisementMonitorManager1_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~AdvertisementMonitorManager1_proxy() = default;
public:
void RegisterMonitor(const sdbus::ObjectPath& application)
{
proxy_.callMethod("RegisterMonitor").onInterface(INTERFACE_NAME).withArguments(application);
}
void UnregisterMonitor(const sdbus::ObjectPath& application)
{
proxy_.callMethod("UnregisterMonitor").onInterface(INTERFACE_NAME).withArguments(application);
}
public:
std::vector<std::string> SupportedMonitorTypes()
{
return proxy_.getProperty("SupportedMonitorTypes").onInterface(INTERFACE_NAME);
}
std::vector<std::string> SupportedFeatures()
{
return proxy_.getProperty("SupportedFeatures").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,57 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__advertisement_monitor_server_h__adaptor__H__
#define __sdbuscpp__advertisement_monitor_server_h__adaptor__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class AdvertisementMonitor1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.AdvertisementMonitor1";
protected:
AdvertisementMonitor1_adaptor(sdbus::IObject& object)
: object_(object)
{
object_.registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); });
object_.registerMethod("Activate").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Activate(); });
object_.registerMethod("DeviceFound").onInterface(INTERFACE_NAME).withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->DeviceFound(device); });
object_.registerMethod("DeviceLost").onInterface(INTERFACE_NAME).withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->DeviceLost(device); });
object_.registerProperty("Type").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Type(); });
object_.registerProperty("RSSILowThreshold").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSILowThreshold(); });
object_.registerProperty("RSSIHighThreshold").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSIHighThreshold(); });
object_.registerProperty("RSSISamplingPeriod").onInterface(INTERFACE_NAME).withGetter([this](){ return this->RSSISamplingPeriod(); });
object_.registerProperty("Patterns").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Patterns(); });
}
~AdvertisementMonitor1_adaptor() = default;
private:
virtual void Release() = 0;
virtual void Activate() = 0;
virtual void DeviceFound(const sdbus::ObjectPath& device) = 0;
virtual void DeviceLost(const sdbus::ObjectPath& device) = 0;
private:
virtual std::string Type() = 0;
virtual int16_t RSSILowThreshold() = 0;
virtual int16_t RSSIHighThreshold() = 0;
virtual uint16_t RSSISamplingPeriod() = 0;
virtual std::vector<sdbus::Struct<uint8_t, uint8_t, std::vector<uint8_t>>> Patterns() = 0;
private:
sdbus::IObject& object_;
};
}} // namespaces
#endif
@@ -0,0 +1,60 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_agent_client_h__adaptor__H__
#define __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_agent_client_h__adaptor__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class Agent1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.Agent1";
protected:
Agent1_adaptor(sdbus::IObject& object)
: object_(&object)
{
object_->registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); });
object_->registerMethod("RequestPinCode").onInterface(INTERFACE_NAME).withInputParamNames("device").withOutputParamNames("pincode").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestPinCode(device); });
object_->registerMethod("DisplayPinCode").onInterface(INTERFACE_NAME).withInputParamNames("device", "pincode").implementedAs([this](const sdbus::ObjectPath& device, const std::string& pincode){ return this->DisplayPinCode(device, pincode); });
object_->registerMethod("RequestPasskey").onInterface(INTERFACE_NAME).withInputParamNames("device").withOutputParamNames("passkey").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestPasskey(device); });
object_->registerMethod("DisplayPasskey").onInterface(INTERFACE_NAME).withInputParamNames("device", "passkey", "entered").implementedAs([this](const sdbus::ObjectPath& device, const uint32_t& passkey, const uint16_t& entered){ return this->DisplayPasskey(device, passkey, entered); });
object_->registerMethod("RequestConfirmation").onInterface(INTERFACE_NAME).withInputParamNames("device", "passkey").implementedAs([this](const sdbus::ObjectPath& device, const uint32_t& passkey){ return this->RequestConfirmation(device, passkey); });
object_->registerMethod("RequestAuthorization").onInterface(INTERFACE_NAME).withInputParamNames("device").implementedAs([this](const sdbus::ObjectPath& device){ return this->RequestAuthorization(device); });
object_->registerMethod("AuthorizeService").onInterface(INTERFACE_NAME).withInputParamNames("device", "uuid").implementedAs([this](const sdbus::ObjectPath& device, const std::string& uuid){ return this->AuthorizeService(device, uuid); });
object_->registerMethod("Cancel").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Cancel(); });
}
Agent1_adaptor(const Agent1_adaptor&) = delete;
Agent1_adaptor& operator=(const Agent1_adaptor&) = delete;
Agent1_adaptor(Agent1_adaptor&&) = default;
Agent1_adaptor& operator=(Agent1_adaptor&&) = default;
~Agent1_adaptor() = default;
private:
virtual void Release() = 0;
virtual std::string RequestPinCode(const sdbus::ObjectPath& device) = 0;
virtual void DisplayPinCode(const sdbus::ObjectPath& device, const std::string& pincode) = 0;
virtual uint32_t RequestPasskey(const sdbus::ObjectPath& device) = 0;
virtual void DisplayPasskey(const sdbus::ObjectPath& device, const uint32_t& passkey, const uint16_t& entered) = 0;
virtual void RequestConfirmation(const sdbus::ObjectPath& device, const uint32_t& passkey) = 0;
virtual void RequestAuthorization(const sdbus::ObjectPath& device) = 0;
virtual void AuthorizeService(const sdbus::ObjectPath& device, const std::string& uuid) = 0;
virtual void Cancel() = 0;
private:
sdbus::IObject* object_;
};
}} // namespaces
#endif
@@ -0,0 +1,56 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_agentmanager_server_h__proxy__H__
#define __sdbuscpp___home_lasan_Dev_nearby_latest_internal_platform_implementation_linux_generated_dbus_bluez_agentmanager_server_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class AgentManager1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.AgentManager1";
protected:
AgentManager1_proxy(sdbus::IProxy& proxy)
: proxy_(&proxy)
{
}
AgentManager1_proxy(const AgentManager1_proxy&) = delete;
AgentManager1_proxy& operator=(const AgentManager1_proxy&) = delete;
AgentManager1_proxy(AgentManager1_proxy&&) = default;
AgentManager1_proxy& operator=(AgentManager1_proxy&&) = default;
~AgentManager1_proxy() = default;
public:
void RegisterAgent(const sdbus::ObjectPath& agent, const std::string& capability)
{
proxy_->callMethod("RegisterAgent").onInterface(INTERFACE_NAME).withArguments(agent, capability);
}
void UnregisterAgent(const sdbus::ObjectPath& agent)
{
proxy_->callMethod("UnregisterAgent").onInterface(INTERFACE_NAME).withArguments(agent);
}
void RequestDefaultAgent(const sdbus::ObjectPath& agent)
{
proxy_->callMethod("RequestDefaultAgent").onInterface(INTERFACE_NAME).withArguments(agent);
}
private:
sdbus::IProxy* proxy_;
};
}} // namespaces
#endif
@@ -1,118 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__gatt_characteristic_client_h__proxy__H__
#define __sdbuscpp__gatt_characteristic_client_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class GattCharacteristic1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.GattCharacteristic1";
protected:
GattCharacteristic1_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~GattCharacteristic1_proxy() = default;
public:
std::vector<uint8_t> ReadValue(const std::map<std::string, sdbus::Variant>& options)
{
std::vector<uint8_t> result;
proxy_.callMethod("ReadValue").onInterface(INTERFACE_NAME).withArguments(options).storeResultsTo(result);
return result;
}
void WriteValue(const std::vector<uint8_t>& value, const std::map<std::string, sdbus::Variant>& options)
{
proxy_.callMethod("WriteValue").onInterface(INTERFACE_NAME).withArguments(value, options);
}
std::tuple<sdbus::UnixFd, uint16_t> AcquireWrite(const std::map<std::string, sdbus::Variant>& options)
{
std::tuple<sdbus::UnixFd, uint16_t> result;
proxy_.callMethod("AcquireWrite").onInterface(INTERFACE_NAME).withArguments(options).storeResultsTo(result);
return result;
}
std::tuple<sdbus::UnixFd, uint16_t> AcquireNotify(const std::map<std::string, sdbus::Variant>& options)
{
std::tuple<sdbus::UnixFd, uint16_t> result;
proxy_.callMethod("AcquireNotify").onInterface(INTERFACE_NAME).withArguments(options).storeResultsTo(result);
return result;
}
void StartNotify()
{
proxy_.callMethod("StartNotify").onInterface(INTERFACE_NAME);
}
void StopNotify()
{
proxy_.callMethod("StopNotify").onInterface(INTERFACE_NAME);
}
public:
uint16_t Handle()
{
return proxy_.getProperty("Handle").onInterface(INTERFACE_NAME);
}
std::string UUID()
{
return proxy_.getProperty("UUID").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Service()
{
return proxy_.getProperty("Service").onInterface(INTERFACE_NAME);
}
std::vector<uint8_t> Value()
{
return proxy_.getProperty("Value").onInterface(INTERFACE_NAME);
}
bool Notifying()
{
return proxy_.getProperty("Notifying").onInterface(INTERFACE_NAME);
}
std::vector<std::string> Flags()
{
return proxy_.getProperty("Flags").onInterface(INTERFACE_NAME);
}
bool WriteAcquired()
{
return proxy_.getProperty("WriteAcquired").onInterface(INTERFACE_NAME);
}
bool NotifyAcquired()
{
return proxy_.getProperty("NotifyAcquired").onInterface(INTERFACE_NAME);
}
uint16_t MTU()
{
return proxy_.getProperty("MTU").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,59 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__generated_dbus_bluez_gatt_characteristic_server_h__adaptor__H__
#define __sdbuscpp__generated_dbus_bluez_gatt_characteristic_server_h__adaptor__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class GattCharacteristic1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.GattCharacteristic1";
protected:
GattCharacteristic1_adaptor(sdbus::IObject& object)
: object_(object)
{
object_.registerMethod("ReadValue").onInterface(INTERFACE_NAME).withInputParamNames("options").withOutputParamNames("value").implementedAs([this](sdbus::Result<std::vector<uint8_t>>&& result, std::map<std::string, sdbus::Variant> options){ this->ReadValue(std::move(result), std::move(options)); });
object_.registerMethod("WriteValue").onInterface(INTERFACE_NAME).withInputParamNames("value", "options").implementedAs([this](sdbus::Result<>&& result, std::vector<uint8_t> value, std::map<std::string, sdbus::Variant> options){ this->WriteValue(std::move(result), std::move(value), std::move(options)); });
object_.registerMethod("StartNotify").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->StartNotify(); });
object_.registerMethod("StopNotify").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->StopNotify(); });
object_.registerMethod("Confirm").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Confirm(); });
object_.registerProperty("UUID").onInterface(INTERFACE_NAME).withGetter([this](){ return this->UUID(); });
object_.registerProperty("Service").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Service(); });
object_.registerProperty("Value").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Value(); });
object_.registerProperty("Notifying").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Notifying(); });
object_.registerProperty("Flags").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Flags(); });
}
~GattCharacteristic1_adaptor() = default;
private:
virtual void ReadValue(sdbus::Result<std::vector<uint8_t>>&& result, std::map<std::string, sdbus::Variant> options) = 0;
virtual void WriteValue(sdbus::Result<>&& result, std::vector<uint8_t> value, std::map<std::string, sdbus::Variant> options) = 0;
virtual void StartNotify() = 0;
virtual void StopNotify() = 0;
virtual void Confirm() = 0;
private:
virtual std::string UUID() = 0;
virtual sdbus::ObjectPath Service() = 0;
virtual std::vector<uint8_t> Value() = 0;
virtual bool Notifying() = 0;
virtual std::vector<std::string> Flags() = 0;
private:
sdbus::IObject& object_;
};
}} // namespaces
#endif
@@ -1,46 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__gatt_manager_client_h__proxy__H__
#define __sdbuscpp__gatt_manager_client_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class GattManager1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.GattManager1";
protected:
GattManager1_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~GattManager1_proxy() = default;
public:
void RegisterApplication(const sdbus::ObjectPath& application, const std::map<std::string, sdbus::Variant>& options)
{
proxy_.callMethod("RegisterApplication").onInterface(INTERFACE_NAME).withArguments(application, options);
}
void UnregisterApplication(const sdbus::ObjectPath& application)
{
proxy_.callMethod("UnregisterApplication").onInterface(INTERFACE_NAME).withArguments(application);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,56 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__gatt_service_client_h__proxy__H__
#define __sdbuscpp__gatt_service_client_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class GattService1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.GattService1";
protected:
GattService1_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~GattService1_proxy() = default;
public:
std::string UUID()
{
return proxy_.getProperty("UUID").onInterface(INTERFACE_NAME);
}
bool Primary()
{
return proxy_.getProperty("Primary").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Device()
{
return proxy_.getProperty("Device").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> Includes()
{
return proxy_.getProperty("Includes").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,45 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__generated_dbus_bluez_gatt_service_server_h__adaptor__H__
#define __sdbuscpp__generated_dbus_bluez_gatt_service_server_h__adaptor__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class GattService1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.GattService1";
protected:
GattService1_adaptor(sdbus::IObject& object)
: object_(object)
{
object_.registerProperty("UUID").onInterface(INTERFACE_NAME).withGetter([this](){ return this->UUID(); });
object_.registerProperty("Primary").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Primary(); });
object_.registerProperty("Device").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Device(); });
object_.registerProperty("Includes").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Includes(); });
}
~GattService1_adaptor() = default;
private:
virtual std::string UUID() = 0;
virtual bool Primary() = 0;
virtual sdbus::ObjectPath Device() = 0;
virtual std::vector<sdbus::ObjectPath> Includes() = 0;
private:
sdbus::IObject& object_;
};
}} // namespaces
#endif
@@ -1,77 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__generated_dbus_bluez_le_advertisement_manager_client_h__proxy__H__
#define __sdbuscpp__generated_dbus_bluez_le_advertisement_manager_client_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class LEAdvertisingManager1_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.LEAdvertisingManager1";
protected:
LEAdvertisingManager1_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~LEAdvertisingManager1_proxy() = default;
public:
void RegisterAdvertisement(const sdbus::ObjectPath& advertisement, const std::map<std::string, sdbus::Variant>& options)
{
proxy_.callMethod("RegisterAdvertisement").onInterface(INTERFACE_NAME).withArguments(advertisement, options);
}
void UnregisterAdvertisement(const sdbus::ObjectPath& service)
{
proxy_.callMethod("UnregisterAdvertisement").onInterface(INTERFACE_NAME).withArguments(service);
}
public:
uint8_t ActiveInstances()
{
return proxy_.getProperty("ActiveInstances").onInterface(INTERFACE_NAME);
}
uint8_t SupportedInstances()
{
return proxy_.getProperty("SupportedInstances").onInterface(INTERFACE_NAME);
}
std::vector<std::string> SupportedIncludes()
{
return proxy_.getProperty("SupportedIncludes").onInterface(INTERFACE_NAME);
}
std::vector<std::string> SupportedSecondaryChannels()
{
return proxy_.getProperty("SupportedSecondaryChannels").onInterface(INTERFACE_NAME);
}
std::vector<std::string> SupportedFeatures()
{
return proxy_.getProperty("SupportedFeatures").onInterface(INTERFACE_NAME);
}
std::map<std::string, sdbus::Variant> SupportedCapabilities()
{
return proxy_.getProperty("SupportedCapabilities").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,65 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__generated_dbus_bluez_le_advertisement_server_h__adaptor__H__
#define __sdbuscpp__generated_dbus_bluez_le_advertisement_server_h__adaptor__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace bluez {
class LEAdvertisement1_adaptor
{
public:
static constexpr const char* INTERFACE_NAME = "org.bluez.LEAdvertisement1";
protected:
LEAdvertisement1_adaptor(sdbus::IObject& object)
: object_(object)
{
object_.registerMethod("Release").onInterface(INTERFACE_NAME).implementedAs([this](){ return this->Release(); });
object_.registerProperty("Type").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Type(); });
object_.registerProperty("ServiceUUIDs").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ServiceUUIDs(); });
object_.registerProperty("ManufacturerData").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ManufacturerData(); });
object_.registerProperty("SolicitUUIDs").onInterface(INTERFACE_NAME).withGetter([this](){ return this->SolicitUUIDs(); });
object_.registerProperty("ServiceData").onInterface(INTERFACE_NAME).withGetter([this](){ return this->ServiceData(); });
object_.registerProperty("Includes").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Includes(); });
object_.registerProperty("LocalName").onInterface(INTERFACE_NAME).withGetter([this](){ return this->LocalName(); });
object_.registerProperty("Duration").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Duration(); });
object_.registerProperty("Timeout").onInterface(INTERFACE_NAME).withGetter([this](){ return this->Timeout(); });
object_.registerProperty("MinInterval").onInterface(INTERFACE_NAME).withGetter([this](){ return this->MinInterval(); });
object_.registerProperty("MaxInterval").onInterface(INTERFACE_NAME).withGetter([this](){ return this->MaxInterval(); });
object_.registerProperty("TxPower").onInterface(INTERFACE_NAME).withGetter([this](){ return this->TxPower(); });
}
~LEAdvertisement1_adaptor() = default;
private:
virtual void Release() = 0;
private:
virtual std::string Type() = 0;
virtual std::vector<std::string> ServiceUUIDs() = 0;
virtual std::map<std::string, sdbus::Variant> ManufacturerData() = 0;
virtual std::vector<std::string> SolicitUUIDs() = 0;
virtual std::map<std::string, sdbus::Variant> ServiceData() = 0;
virtual std::vector<std::string> Includes() = 0;
virtual std::string LocalName() = 0;
virtual uint16_t Duration() = 0;
virtual uint16_t Timeout() = 0;
virtual uint32_t MinInterval() = 0;
virtual uint32_t MaxInterval() = 0;
virtual int16_t TxPower() = 0;
private:
sdbus::IObject& object_;
};
}} // namespaces
#endif
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.AdvertisementMonitor1">
<method name="Release">
</method>
<method name="Activate">
</method>
<method name="DeviceFound">
<arg type='o' name="device" direction="in"/>
</method>
<method name="DeviceLost">
<arg type='o' name="device" direction="in"/>
</method>
<property name="Type" type="s" access="read">
</property>
<property name="RSSILowThreshold" type="n" access="read">
</property>
<property name="RSSIHighThreshold" type="n" access="read">
</property>
<property name="RSSISamplingPeriod" type="q" access="read">
</property>
<property name="Patterns" type="a(yyay)" access="read">
</property>
</interface>
</node>
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.AdvertisementMonitorManager1">
<method name="RegisterMonitor">
<arg name="application" type="o" direction="in" />
</method>
<method name="UnregisterMonitor">
<arg name="application" type="o" direction="in" />
</method>
<property name="SupportedMonitorTypes" type="as" access="read" />
<property name="SupportedFeatures" type="as" access="read" />
</interface>
</node>
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.Agent1">
<method name="Release"/>
<method name="RequestPinCode">
<arg name="device" type="o" direction="in"/>
<arg name="pincode" type="s" direction="out"/>
</method>
<method name="DisplayPinCode">
<arg name="device" type="o" direction="in"/>
<arg name="pincode" type="s" direction="in"/>
</method>
<method name="RequestPasskey">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="out"/>
</method>
<method name="DisplayPasskey">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="in"/>
<arg name="entered" type="q" direction="in"/>
</method>
<method name="RequestConfirmation">
<arg name="device" type="o" direction="in"/>
<arg name="passkey" type="u" direction="in"/>
</method>
<method name="RequestAuthorization">
<arg name="device" type="o" direction="in"/>
</method>
<method name="AuthorizeService">
<arg name="device" type="o" direction="in"/>
<arg name="uuid" type="s" direction="in"/>
</method>
<method name="Cancel"/>
</interface>
</node>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.AgentManager1">
<method name="RegisterAgent">
<arg name="agent" type="o" direction="in"/>
<arg name="capability" type="s" direction="in"/>
</method>
<method name="UnregisterAgent">
<arg name="agent" type="o" direction="in"/>
</method>
<method name="RequestDefaultAgent">
<arg name="agent" type="o" direction="in"/>
</method>
</interface>
</node>
@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.GattCharacteristic1">
<method name="ReadValue">
<arg name="options" type="a{sv}" direction="in" />
<arg name="value" type="ay" direction="out" />
</method>
<method name="WriteValue">
<arg name="value" type="ay" direction="in" />
<arg name="options" type="a{sv}" direction="in" />
</method>
<method name="AcquireWrite">
<arg name="options" type="a{sv}" direction="in" />
<arg name="fd" type="h" direction="out" />
<arg name="mtu" type="q" direction="out" />
</method>
<method name="AcquireNotify">
<arg name="options" type="a{sv}" direction="in" />
<arg name="fd" type="h" direction="out" />
<arg name="mtu" type="q" direction="out" />
</method>
<method name="StartNotify" />
<method name="StopNotify" />
<property name="Handle" type="q" access="read" />
<property name="UUID" type="s" access="read" />
<property name="Service" type="o" access="read" />
<property name="Value" type="ay" access="read" />
<property name="Notifying" type="b" access="read" />
<property name="Flags" type="as" access="read" />
<property name="WriteAcquired" type="b" access="read" />
<property name="NotifyAcquired" type="b" access="read" />
<property name="MTU" type="q" access="read" />
</interface>
</node>
@@ -1,28 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.GattCharacteristic1">
<method name="ReadValue">
<annotation name="org.freedesktop.DBus.Method.Async" value="server" />
<arg name="options" type="a{sv}" direction="in"/>
<arg name="value" type="ay" direction="out"/>
</method>
<method name="WriteValue">
<annotation name="org.freedesktop.DBus.Method.Async" value="server" />
<arg name="value" type="ay" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
</method>
<method name="StartNotify">
</method>
<method name="StopNotify">
</method>
<method name="Confirm">
</method>
<property name="UUID" type="s" access="read"></property>
<property name="Service" type="o" access="read"></property>
<property name="Value" type="ay" access="read"></property>
<property name="Notifying" type="b" access="read"></property>
<property name="Flags" type="as" access="read"></property>
</interface>
</node>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.GattManager1">
<method name="RegisterApplication">
<arg name="application" type="o" direction="in" />
<arg name="options" type="a{sv}" direction="in" />
</method>
<method name="UnregisterApplication">
<arg name="application" type="o" direction="in" />
</method>
</interface>
</node>
@@ -1,10 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.GattService1">
<property name="UUID" type="s" access="read"></property>
<property name="Primary" type="b" access="read"></property>
<property name="Device" type="o" access="read"></property>
<property name="Includes" type="ao" access="read"></property>
</interface>
</node>
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.LEAdvertisement1">
<method name="Release"/>
<property name="Type" type="s" access="read"/>
<property name="ServiceUUIDs" type="as" access="read"/>
<property name="ManufacturerData" type="a{sv}" access="read"/>
<property name="SolicitUUIDs" type="as" access="read"/>
<property name="ServiceData" type="a{sv}" access="read"/>
<property name="Includes" type="as" access="read"/>
<property name="LocalName" type="s" access="read"/>
<property name="Duration" type="q" access="read"/>
<property name="Timeout" type="q" access="read"/>
<property name="MinInterval" type="u" access="read"/>
<property name="MaxInterval" type="u" access="read"/>
<property name="TxPower" type="n" access="read"/>
</interface>
</node>
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.bluez.LEAdvertisingManager1">
<method name="RegisterAdvertisement">
<arg name="advertisement" type="o" direction="in" />
<arg name="options" type="a{sv}" direction="in" />
</method>
<method name="UnregisterAdvertisement">
<arg name="service" type="o" direction="in" />
</method>
<property name="ActiveInstances" type="y" access="read" />
<property name="SupportedInstances" type="y" access="read" />
<property name="SupportedIncludes" type="as" access="read" />
<property name="SupportedSecondaryChannels" type="as" access="read" />
<property name="SupportedFeatures" type="as" access="read" />
<property name="SupportedCapabilities" type="a{sv}" access="read" />
</interface>
</node>
@@ -1,87 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_accesspoint_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_accesspoint_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
namespace NetworkManager {
class AccessPoint_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.AccessPoint";
protected:
AccessPoint_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~AccessPoint_proxy() = default;
public:
uint32_t Flags()
{
return proxy_.getProperty("Flags").onInterface(INTERFACE_NAME);
}
uint32_t WpaFlags()
{
return proxy_.getProperty("WpaFlags").onInterface(INTERFACE_NAME);
}
uint32_t RsnFlags()
{
return proxy_.getProperty("RsnFlags").onInterface(INTERFACE_NAME);
}
std::vector<uint8_t> Ssid()
{
return proxy_.getProperty("Ssid").onInterface(INTERFACE_NAME);
}
uint32_t Frequency()
{
return proxy_.getProperty("Frequency").onInterface(INTERFACE_NAME);
}
std::string HwAddress()
{
return proxy_.getProperty("HwAddress").onInterface(INTERFACE_NAME);
}
uint32_t Mode()
{
return proxy_.getProperty("Mode").onInterface(INTERFACE_NAME);
}
uint32_t MaxBitrate()
{
return proxy_.getProperty("MaxBitrate").onInterface(INTERFACE_NAME);
}
uint8_t Strength()
{
return proxy_.getProperty("Strength").onInterface(INTERFACE_NAME);
}
int32_t LastSeen()
{
return proxy_.getProperty("LastSeen").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}}} // namespaces
#endif
@@ -1,126 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_connection_active_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_connection_active_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
namespace NetworkManager {
namespace Connection {
class Active_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.Connection.Active";
protected:
Active_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const uint32_t& state, const uint32_t& reason){ this->onStateChanged(state, reason); });
}
~Active_proxy() = default;
virtual void onStateChanged(const uint32_t& state, const uint32_t& reason) = 0;
public:
sdbus::ObjectPath Connection()
{
return proxy_.getProperty("Connection").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath SpecificObject()
{
return proxy_.getProperty("SpecificObject").onInterface(INTERFACE_NAME);
}
std::string Id()
{
return proxy_.getProperty("Id").onInterface(INTERFACE_NAME);
}
std::string Uuid()
{
return proxy_.getProperty("Uuid").onInterface(INTERFACE_NAME);
}
std::string Type()
{
return proxy_.getProperty("Type").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> Devices()
{
return proxy_.getProperty("Devices").onInterface(INTERFACE_NAME);
}
uint32_t State()
{
return proxy_.getProperty("State").onInterface(INTERFACE_NAME);
}
uint32_t StateFlags()
{
return proxy_.getProperty("StateFlags").onInterface(INTERFACE_NAME);
}
bool Default()
{
return proxy_.getProperty("Default").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Ip4Config()
{
return proxy_.getProperty("Ip4Config").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Dhcp4Config()
{
return proxy_.getProperty("Dhcp4Config").onInterface(INTERFACE_NAME);
}
bool Default6()
{
return proxy_.getProperty("Default6").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Ip6Config()
{
return proxy_.getProperty("Ip6Config").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Dhcp6Config()
{
return proxy_.getProperty("Dhcp6Config").onInterface(INTERFACE_NAME);
}
bool Vpn()
{
return proxy_.getProperty("Vpn").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Controller()
{
return proxy_.getProperty("Controller").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath Master()
{
return proxy_.getProperty("Master").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}}}} // namespaces
#endif
@@ -1,64 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_device_wifip2p_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_device_wifip2p_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
namespace NetworkManager {
namespace Device {
class WifiP2P_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.Device.WifiP2P";
protected:
WifiP2P_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_.uponSignal("PeerAdded").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& peer){ this->onPeerAdded(peer); });
proxy_.uponSignal("PeerRemoved").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& peer){ this->onPeerRemoved(peer); });
}
~WifiP2P_proxy() = default;
virtual void onPeerAdded(const sdbus::ObjectPath& peer) = 0;
virtual void onPeerRemoved(const sdbus::ObjectPath& peer) = 0;
public:
void StartFind(const std::map<std::string, sdbus::Variant>& options)
{
proxy_.callMethod("StartFind").onInterface(INTERFACE_NAME).withArguments(options);
}
void StopFind()
{
proxy_.callMethod("StopFind").onInterface(INTERFACE_NAME);
}
public:
std::string HwAddress()
{
return proxy_.getProperty("HwAddress").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> Peers()
{
return proxy_.getProperty("Peers").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}}}} // namespaces
#endif
@@ -1,103 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_device_wireless_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_device_wireless_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
namespace NetworkManager {
namespace Device {
class Wireless_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.Device.Wireless";
protected:
Wireless_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_.uponSignal("AccessPointAdded").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& access_point){ this->onAccessPointAdded(access_point); });
proxy_.uponSignal("AccessPointRemoved").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& access_point){ this->onAccessPointRemoved(access_point); });
}
~Wireless_proxy() = default;
virtual void onAccessPointAdded(const sdbus::ObjectPath& access_point) = 0;
virtual void onAccessPointRemoved(const sdbus::ObjectPath& access_point) = 0;
public:
std::vector<sdbus::ObjectPath> GetAccessPoints()
{
std::vector<sdbus::ObjectPath> result;
proxy_.callMethod("GetAccessPoints").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
std::vector<sdbus::ObjectPath> GetAllAccessPoints()
{
std::vector<sdbus::ObjectPath> result;
proxy_.callMethod("GetAllAccessPoints").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
void RequestScan(const std::map<std::string, sdbus::Variant>& options)
{
proxy_.callMethod("RequestScan").onInterface(INTERFACE_NAME).withArguments(options);
}
public:
std::string HwAddress()
{
return proxy_.getProperty("HwAddress").onInterface(INTERFACE_NAME);
}
std::string PermHwAddress()
{
return proxy_.getProperty("PermHwAddress").onInterface(INTERFACE_NAME);
}
uint32_t Mode()
{
return proxy_.getProperty("Mode").onInterface(INTERFACE_NAME);
}
uint32_t Bitrate()
{
return proxy_.getProperty("Bitrate").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> AccessPoints()
{
return proxy_.getProperty("AccessPoints").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath ActiveAccessPoint()
{
return proxy_.getProperty("ActiveAccessPoint").onInterface(INTERFACE_NAME);
}
uint32_t WirelessCapabilities()
{
return proxy_.getProperty("WirelessCapabilities").onInterface(INTERFACE_NAME);
}
int64_t LastScan()
{
return proxy_.getProperty("LastScan").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}}}} // namespaces
#endif
@@ -1,102 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_ip4config_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_ip4config_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
namespace NetworkManager {
class IP4Config_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager.IP4Config";
protected:
IP4Config_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
~IP4Config_proxy() = default;
public:
std::vector<std::vector<uint32_t>> Addresses()
{
return proxy_.getProperty("Addresses").onInterface(INTERFACE_NAME);
}
std::vector<std::map<std::string, sdbus::Variant>> AddressData()
{
return proxy_.getProperty("AddressData").onInterface(INTERFACE_NAME);
}
std::string Gateway()
{
return proxy_.getProperty("Gateway").onInterface(INTERFACE_NAME);
}
std::vector<std::vector<uint32_t>> Routes()
{
return proxy_.getProperty("Routes").onInterface(INTERFACE_NAME);
}
std::vector<std::map<std::string, sdbus::Variant>> RouteData()
{
return proxy_.getProperty("RouteData").onInterface(INTERFACE_NAME);
}
std::vector<uint32_t> Nameservers()
{
return proxy_.getProperty("Nameservers").onInterface(INTERFACE_NAME);
}
std::vector<std::map<std::string, sdbus::Variant>> NameserverData()
{
return proxy_.getProperty("NameserverData").onInterface(INTERFACE_NAME);
}
std::vector<std::string> Domains()
{
return proxy_.getProperty("Domains").onInterface(INTERFACE_NAME);
}
std::vector<std::string> Searches()
{
return proxy_.getProperty("Searches").onInterface(INTERFACE_NAME);
}
std::vector<std::string> DnsOptions()
{
return proxy_.getProperty("DnsOptions").onInterface(INTERFACE_NAME);
}
int32_t DnsPriority()
{
return proxy_.getProperty("DnsPriority").onInterface(INTERFACE_NAME);
}
std::vector<uint32_t> WinsServers()
{
return proxy_.getProperty("WinsServers").onInterface(INTERFACE_NAME);
}
std::vector<std::string> WinsServerData()
{
return proxy_.getProperty("WinsServerData").onInterface(INTERFACE_NAME);
}
private:
sdbus::IProxy& proxy_;
};
}}} // namespaces
#endif
@@ -1,320 +0,0 @@
/*
* This file was automatically generated by sdbus-c++-xml2cpp; DO NOT EDIT!
*/
#ifndef __sdbuscpp__networkmanager_client_glue_h__proxy__H__
#define __sdbuscpp__networkmanager_client_glue_h__proxy__H__
#include <sdbus-c++/sdbus-c++.h>
#include <string>
#include <tuple>
namespace org {
namespace freedesktop {
class NetworkManager_proxy
{
public:
static constexpr const char* INTERFACE_NAME = "org.freedesktop.NetworkManager";
protected:
NetworkManager_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_.uponSignal("CheckPermissions").onInterface(INTERFACE_NAME).call([this](){ this->onCheckPermissions(); });
proxy_.uponSignal("StateChanged").onInterface(INTERFACE_NAME).call([this](const uint32_t& state){ this->onStateChanged(state); });
proxy_.uponSignal("DeviceAdded").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& device_path){ this->onDeviceAdded(device_path); });
proxy_.uponSignal("DeviceRemoved").onInterface(INTERFACE_NAME).call([this](const sdbus::ObjectPath& device_path){ this->onDeviceRemoved(device_path); });
}
~NetworkManager_proxy() = default;
virtual void onCheckPermissions() = 0;
virtual void onStateChanged(const uint32_t& state) = 0;
virtual void onDeviceAdded(const sdbus::ObjectPath& device_path) = 0;
virtual void onDeviceRemoved(const sdbus::ObjectPath& device_path) = 0;
public:
void Reload(const uint32_t& flags)
{
proxy_.callMethod("Reload").onInterface(INTERFACE_NAME).withArguments(flags);
}
std::vector<sdbus::ObjectPath> GetDevices()
{
std::vector<sdbus::ObjectPath> result;
proxy_.callMethod("GetDevices").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
std::vector<sdbus::ObjectPath> GetAllDevices()
{
std::vector<sdbus::ObjectPath> result;
proxy_.callMethod("GetAllDevices").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
sdbus::ObjectPath GetDeviceByIpIface(const std::string& iface)
{
sdbus::ObjectPath result;
proxy_.callMethod("GetDeviceByIpIface").onInterface(INTERFACE_NAME).withArguments(iface).storeResultsTo(result);
return result;
}
sdbus::ObjectPath ActivateConnection(const sdbus::ObjectPath& connection, const sdbus::ObjectPath& device, const sdbus::ObjectPath& specific_object)
{
sdbus::ObjectPath result;
proxy_.callMethod("ActivateConnection").onInterface(INTERFACE_NAME).withArguments(connection, device, specific_object).storeResultsTo(result);
return result;
}
std::tuple<sdbus::ObjectPath, sdbus::ObjectPath> AddAndActivateConnection(const std::map<std::string, std::map<std::string, sdbus::Variant>>& connection, const sdbus::ObjectPath& device, const sdbus::ObjectPath& specific_object)
{
std::tuple<sdbus::ObjectPath, sdbus::ObjectPath> result;
proxy_.callMethod("AddAndActivateConnection").onInterface(INTERFACE_NAME).withArguments(connection, device, specific_object).storeResultsTo(result);
return result;
}
std::tuple<sdbus::ObjectPath, sdbus::ObjectPath, std::map<std::string, sdbus::Variant>> AddAndActivateConnection2(const std::map<std::string, std::map<std::string, sdbus::Variant>>& connection, const sdbus::ObjectPath& device, const sdbus::ObjectPath& specific_object, const std::map<std::string, sdbus::Variant>& options)
{
std::tuple<sdbus::ObjectPath, sdbus::ObjectPath, std::map<std::string, sdbus::Variant>> result;
proxy_.callMethod("AddAndActivateConnection2").onInterface(INTERFACE_NAME).withArguments(connection, device, specific_object, options).storeResultsTo(result);
return result;
}
void DeactivateConnection(const sdbus::ObjectPath& active_connection)
{
proxy_.callMethod("DeactivateConnection").onInterface(INTERFACE_NAME).withArguments(active_connection);
}
void Sleep(const bool& sleep)
{
proxy_.callMethod("Sleep").onInterface(INTERFACE_NAME).withArguments(sleep);
}
void Enable(const bool& enable)
{
proxy_.callMethod("Enable").onInterface(INTERFACE_NAME).withArguments(enable);
}
std::map<std::string, std::string> GetPermissions()
{
std::map<std::string, std::string> result;
proxy_.callMethod("GetPermissions").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
void SetLogging(const std::string& level, const std::string& domains)
{
proxy_.callMethod("SetLogging").onInterface(INTERFACE_NAME).withArguments(level, domains);
}
std::tuple<std::string, std::string> GetLogging()
{
std::tuple<std::string, std::string> result;
proxy_.callMethod("GetLogging").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
uint32_t CheckConnectivity()
{
uint32_t result;
proxy_.callMethod("CheckConnectivity").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
uint32_t state()
{
uint32_t result;
proxy_.callMethod("state").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result;
}
sdbus::ObjectPath CheckpointCreate(const std::vector<sdbus::ObjectPath>& devices, const uint32_t& rollback_timeout, const uint32_t& flags)
{
sdbus::ObjectPath result;
proxy_.callMethod("CheckpointCreate").onInterface(INTERFACE_NAME).withArguments(devices, rollback_timeout, flags).storeResultsTo(result);
return result;
}
void CheckpointDestroy(const sdbus::ObjectPath& checkpoint)
{
proxy_.callMethod("CheckpointDestroy").onInterface(INTERFACE_NAME).withArguments(checkpoint);
}
std::map<std::string, uint32_t> CheckpointRollback(const sdbus::ObjectPath& checkpoint)
{
std::map<std::string, uint32_t> result;
proxy_.callMethod("CheckpointRollback").onInterface(INTERFACE_NAME).withArguments(checkpoint).storeResultsTo(result);
return result;
}
void CheckpointAdjustRollbackTimeout(const sdbus::ObjectPath& checkpoint, const uint32_t& add_timeout)
{
proxy_.callMethod("CheckpointAdjustRollbackTimeout").onInterface(INTERFACE_NAME).withArguments(checkpoint, add_timeout);
}
public:
std::vector<sdbus::ObjectPath> Devices()
{
return proxy_.getProperty("Devices").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> AllDevices()
{
return proxy_.getProperty("AllDevices").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> Checkpoints()
{
return proxy_.getProperty("Checkpoints").onInterface(INTERFACE_NAME);
}
bool NetworkingEnabled()
{
return proxy_.getProperty("NetworkingEnabled").onInterface(INTERFACE_NAME);
}
bool WirelessEnabled()
{
return proxy_.getProperty("WirelessEnabled").onInterface(INTERFACE_NAME);
}
void WirelessEnabled(const bool& value)
{
proxy_.setProperty("WirelessEnabled").onInterface(INTERFACE_NAME).toValue(value);
}
bool WirelessHardwareEnabled()
{
return proxy_.getProperty("WirelessHardwareEnabled").onInterface(INTERFACE_NAME);
}
bool WwanEnabled()
{
return proxy_.getProperty("WwanEnabled").onInterface(INTERFACE_NAME);
}
void WwanEnabled(const bool& value)
{
proxy_.setProperty("WwanEnabled").onInterface(INTERFACE_NAME).toValue(value);
}
bool WwanHardwareEnabled()
{
return proxy_.getProperty("WwanHardwareEnabled").onInterface(INTERFACE_NAME);
}
bool WimaxEnabled()
{
return proxy_.getProperty("WimaxEnabled").onInterface(INTERFACE_NAME);
}
void WimaxEnabled(const bool& value)
{
proxy_.setProperty("WimaxEnabled").onInterface(INTERFACE_NAME).toValue(value);
}
bool WimaxHardwareEnabled()
{
return proxy_.getProperty("WimaxHardwareEnabled").onInterface(INTERFACE_NAME);
}
uint32_t RadioFlags()
{
return proxy_.getProperty("RadioFlags").onInterface(INTERFACE_NAME);
}
std::vector<sdbus::ObjectPath> ActiveConnections()
{
return proxy_.getProperty("ActiveConnections").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath PrimaryConnection()
{
return proxy_.getProperty("PrimaryConnection").onInterface(INTERFACE_NAME);
}
std::string PrimaryConnectionType()
{
return proxy_.getProperty("PrimaryConnectionType").onInterface(INTERFACE_NAME);
}
uint32_t Metered()
{
return proxy_.getProperty("Metered").onInterface(INTERFACE_NAME);
}
sdbus::ObjectPath ActivatingConnection()
{
return proxy_.getProperty("ActivatingConnection").onInterface(INTERFACE_NAME);
}
bool Startup()
{
return proxy_.getProperty("Startup").onInterface(INTERFACE_NAME);
}
std::string Version()
{
return proxy_.getProperty("Version").onInterface(INTERFACE_NAME);
}
std::vector<uint32_t> VersionInfo()
{
return proxy_.getProperty("VersionInfo").onInterface(INTERFACE_NAME);
}
std::vector<uint32_t> Capabilities()
{
return proxy_.getProperty("Capabilities").onInterface(INTERFACE_NAME);
}
uint32_t State()
{
return proxy_.getProperty("State").onInterface(INTERFACE_NAME);
}
uint32_t Connectivity()
{
return proxy_.getProperty("Connectivity").onInterface(INTERFACE_NAME);
}
bool ConnectivityCheckAvailable()
{
return proxy_.getProperty("ConnectivityCheckAvailable").onInterface(INTERFACE_NAME);
}
bool ConnectivityCheckEnabled()
{
return proxy_.getProperty("ConnectivityCheckEnabled").onInterface(INTERFACE_NAME);
}
void ConnectivityCheckEnabled(const bool& value)
{
proxy_.setProperty("ConnectivityCheckEnabled").onInterface(INTERFACE_NAME).toValue(value);
}
std::string ConnectivityCheckUri()
{
return proxy_.getProperty("ConnectivityCheckUri").onInterface(INTERFACE_NAME);
}
std::map<std::string, sdbus::Variant> GlobalDnsConfiguration()
{
return proxy_.getProperty("GlobalDnsConfiguration").onInterface(INTERFACE_NAME);
}
void GlobalDnsConfiguration(const std::map<std::string, sdbus::Variant>& value)
{
proxy_.setProperty("GlobalDnsConfiguration").onInterface(INTERFACE_NAME).toValue(value);
}
private:
sdbus::IProxy& proxy_;
};
}} // namespaces
#endif
@@ -1,99 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.AccessPoint:
@short_description: Wi-Fi Access Point.
-->
<interface name="org.freedesktop.NetworkManager.AccessPoint">
<!--
Flags:
Flags describing the capabilities of the access point.
Returns: <link linkend="NM80211ApFlags">NM80211ApFlags</link>
-->
<property name="Flags" type="u" access="read"/>
<!--
WpaFlags:
Flags describing the access point's capabilities according to WPA (Wifi
Protected Access).
Returns: <link linkend="NM80211ApSecurityFlags">NM80211ApSecurityFlags</link>
-->
<property name="WpaFlags" type="u" access="read"/>
<!--
RsnFlags:
Flags describing the access point's capabilities according to the RSN
(Robust Secure Network) protocol.
Returns: <link linkend="NM80211ApSecurityFlags">NM80211ApSecurityFlags</link>
-->
<property name="RsnFlags" type="u" access="read"/>
<!--
Ssid:
The Service Set Identifier identifying the access point.
-->
<property name="Ssid" type="ay" access="read">
<!-- gdbus-codegen assumes that "ay" means "non-UTF-8 string" and
won't deal with '\0' bytes correctly.
-->
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="1"/>
</property>
<!--
Frequency:
The radio channel frequency in use by the access point, in MHz.
-->
<property name="Frequency" type="u" access="read"/>
<!--
HwAddress:
The hardware address (BSSID) of the access point.
-->
<property name="HwAddress" type="s" access="read"/>
<!--
Mode:
Describes the operating mode of the access point.
Returns: <link linkend="NM80211Mode">NM80211Mode</link>
-->
<property name="Mode" type="u" access="read"/>
<!--
MaxBitrate:
The maximum bitrate this access point is capable of, in kilobits/second
(Kb/s).
-->
<property name="MaxBitrate" type="u" access="read"/>
<!--
Strength:
The current signal quality of the access point, in percent.
-->
<property name="Strength" type="y" access="read"/>
<!--
LastSeen:
The timestamp (in CLOCK_BOOTTIME seconds) for the last time the access
point was found in scan results. A value of -1 means the access point has
never been found in scan results.
-->
<property name="LastSeen" type="i" access="read"/>
</interface>
</node>
@@ -1,185 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.Connection.Active:
@short_description: Active Connection.
Objects that implement the Connection.Active interface represent an
attempt to connect to a network using the details provided by a Connection
object. The Connection.Active object tracks the life-cycle of the
connection attempt and if successful indicates whether the connected
network is the "default" or preferred network for access. NetworkManager
has the concept of connections, which can be thought of as settings, a
profile or a configuration that can be applied on a networking device.
Such settings-connections are exposed as D-Bus object and the
active-connection expresses this relationship between device and
settings-connection. At any time a settings-connection can only be
activated on one device and vice versa. However, during activation and
deactivation multiple active-connections can reference the same device or
settings-connection as they are waiting to be activated or to be
deactivated.
-->
<interface name="org.freedesktop.NetworkManager.Connection.Active">
<annotation name="org.gtk.GDBus.C.Name" value="ActiveConnection"/>
<!--
Connection:
The path of the connection.
-->
<property name="Connection" type="o" access="read"/>
<!--
SpecificObject:
A specific object associated with the active connection. This property
reflects the specific object used during connection activation, and will
not change over the lifetime of the ActiveConnection once set.
-->
<property name="SpecificObject" type="o" access="read"/>
<!--
Id:
The ID of the connection, provided as a convenience so that clients do not
have to retrieve all connection details.
-->
<property name="Id" type="s" access="read"/>
<!--
Uuid:
The UUID of the connection, provided as a convenience so that clients do
not have to retrieve all connection details.
-->
<property name="Uuid" type="s" access="read"/>
<!--
Type:
The type of the connection, provided as a convenience so that clients do
not have to retrieve all connection details.
-->
<property name="Type" type="s" access="read"/>
<!--
Devices:
Array of object paths representing devices which are part of this active
connection.
-->
<property name="Devices" type="ao" access="read"/>
<!--
State:
The state of this active connection.
Returns: <link linkend="NMActiveConnectionState">NMActiveConnectionState</link>
-->
<property name="State" type="u" access="read"/>
<!--
StateFlags:
The state flags of this active connection.
Returns: <link linkend="NMActivationStateFlags">NMActivationStateFlags</link>
-->
<property name="StateFlags" type="u" access="read"/>
<!--
StateChanged:
@state: (<link linkend="NMActiveConnectionState">NMActiveConnectionState</link>) The new state of the active connection.
@reason: (<link linkend="NMActiveConnectionStateReason">NMActiveConnectionStateReason</link>) Reason code describing the change to the new state.
@since: 1.8
Emitted when the state of the active connection has changed.
-->
<signal name="StateChanged">
<arg name="state" type="u"/>
<arg name="reason" type="u"/>
</signal>
<!--
Default:
Whether this active connection is the default IPv4 connection, i.e.
whether it currently owns the default IPv4 route.
-->
<property name="Default" type="b" access="read"/>
<!--
Ip4Config:
Object path of the Ip4Config object describing the configuration of the
connection. Only valid when the connection is in the
NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
-->
<property name="Ip4Config" type="o" access="read"/>
<!--
Dhcp4Config:
Object path of the Dhcp4Config object describing the DHCP options returned
by the DHCP server (assuming the connection used DHCP). Only valid when
the connection is in the NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
-->
<property name="Dhcp4Config" type="o" access="read"/>
<!--
Default6:
Whether this active connection is the default IPv6 connection, i.e.
whether it currently owns the default IPv6 route.
-->
<property name="Default6" type="b" access="read"/>
<!--
Ip6Config:
Object path of the Ip6Config object describing the configuration of the
connection. Only valid when the connection is in the
NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
-->
<property name="Ip6Config" type="o" access="read"/>
<!--
Dhcp6Config:
Object path of the Dhcp6Config object describing the DHCP options returned
by the DHCP server (assuming the connection used DHCP). Only valid when
the connection is in the NM_ACTIVE_CONNECTION_STATE_ACTIVATED state.
-->
<property name="Dhcp6Config" type="o" access="read"/>
<!--
Vpn:
Whether this active connection is also a VPN connection.
-->
<property name="Vpn" type="b" access="read"/>
<!--
Controller:
@Since: 1.44, 1.42.2
The path to the controller device if the connection is a port. This
property replaces the deprecated 'Master' property.
-->
<property name="Controller" type="o" access="read"/>
<!--
Master:
The path to the controller device if the connection is a port.
This property is deprecated in favor of the 'Controller'
property since 1.44 and 1.42.2.
-->
<property name="Master" type="o" access="read"/>
</interface>
</node>
@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.Device.WifiP2P:
@short_description: Wi-Fi P2P Device.
@since: 1.16
-->
<interface name="org.freedesktop.NetworkManager.Device.WifiP2P">
<annotation name="org.gtk.GDBus.C.Name" value="Device_Wifi_P2P"/>
<!--
HwAddress:
The active hardware address of the device.
DEPRECATED. Use the "HwAddress" property in "org.freedesktop.NetworkManager.Device" instead which exists since version NetworkManager 1.24.0.
-->
<property name="HwAddress" type="s" access="read"/>
<!--
Peers:
List of object paths of peers visible to this Wi-Fi P2P device.
-->
<property name="Peers" type="ao" access="read"/>
<!--
StartFind:
@options: Options of find.
Start a find operation for Wi-Fi P2P peers.
The %options argument accepts the following keys:
<variablelist>
<varlistentry>
<term><literal>i timeout</literal>:</term>
<listitem><para>Timeout value in the range of 1-600 seconds.</para>
<para>The default is 30 seconds.</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="StartFind">
<arg name="options" type="a{sv}" direction="in"/>
</method>
<!--
StopFind:
Stop an ongoing find operation again.
-->
<method name="StopFind">
</method>
<!--
PeerAdded:
@peer: The object path of the newly found access point.
Emitted when a new Wi-Fi P2P peer is found by the device.
-->
<signal name="PeerAdded">
<arg name="peer" type="o"/>
</signal>
<!--
PeerRemoved:
@peer: The object path of the Wi-Fi P2P peer that has disappeared.
Emitted when a Wi-Fi P2P peer disappears from view of the device.
-->
<signal name="PeerRemoved">
<arg name="peer" type="o"/>
</signal>
</interface>
</node>
@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.Device.Wireless:
@short_description: Wi-Fi Device.
-->
<interface name="org.freedesktop.NetworkManager.Device.Wireless">
<annotation name="org.gtk.GDBus.C.Name" value="DeviceWifi"/>
<!--
GetAccessPoints:
@access_points: List of access point object paths.
DEPRECATED. Get the list of access points visible to this device. Note
that this list does not include access points which hide their SSID. To
retrieve a list of all access points (including hidden ones) use the
GetAllAccessPoints() method.
-->
<method name="GetAccessPoints">
<arg name="access_points" type="ao" direction="out"/>
</method>
<!--
GetAllAccessPoints:
@access_points: List of access point object paths.
Get the list of all access points visible to this device, including hidden
ones for which the SSID is not yet known.
-->
<method name="GetAllAccessPoints">
<arg name="access_points" type="ao" direction="out"/>
</method>
<!--
RequestScan:
@options: Options of scan. Currently, 'ssids' option with value of "aay" type is supported.
Request the device to scan. To know when the scan is finished, use the "PropertiesChanged" signal from "org.freedesktop.DBus.Properties" to listen to changes to the "LastScan" property.
-->
<method name="RequestScan">
<arg name="options" type="a{sv}" direction="in"/>
</method>
<!--
HwAddress:
The active hardware address of the device.
DEPRECATED. Use the "HwAddress" property in "org.freedesktop.NetworkManager.Device" instead which exists since version NetworkManager 1.24.0.
-->
<property name="HwAddress" type="s" access="read"/>
<!--
PermHwAddress:
The permanent hardware address of the device.
-->
<property name="PermHwAddress" type="s" access="read"/>
<!--
Mode:
The operating mode of the wireless device.
Returns: <link linkend="NM80211Mode">NM80211Mode</link>
-->
<property name="Mode" type="u" access="read"/>
<!--
Bitrate:
The bit rate currently used by the wireless device, in kilobits/second
(Kb/s).
-->
<property name="Bitrate" type="u" access="read"/>
<!--
AccessPoints:
List of object paths of access point visible to this wireless device.
-->
<property name="AccessPoints" type="ao" access="read"/>
<!--
ActiveAccessPoint:
Object path of the access point currently used by the wireless device.
-->
<property name="ActiveAccessPoint" type="o" access="read"/>
<!--
WirelessCapabilities:
The capabilities of the wireless device.
Returns: <link linkend="NMDeviceWifiCapabilities">NMDeviceWifiCapabilities</link>
-->
<property name="WirelessCapabilities" type="u" access="read"/>
<!--
LastScan:
@since: 1.12
The timestamp (in CLOCK_BOOTTIME milliseconds) for the last finished network scan.
A value of -1 means the device never scanned for access points.
-->
<property name="LastScan" type="x" access="read"/>
<!--
AccessPointAdded:
@access_point: The object path of the newly found access point.
Emitted when a new access point is found by the device.
-->
<signal name="AccessPointAdded">
<arg name="access_point" type="o"/>
</signal>
<!--
AccessPointRemoved:
@access_point: The object path of the access point that has disappeared.
Emitted when an access point disappears from view of the device.
-->
<signal name="AccessPointRemoved">
<arg name="access_point" type="o"/>
</signal>
</interface>
</node>
@@ -1,117 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/">
<!--
org.freedesktop.NetworkManager.IP4Config:
@short_description: IPv4 Configuration Set.
-->
<interface name="org.freedesktop.NetworkManager.IP4Config">
<!--
Addresses:
Array of arrays of IPv4 address/prefix/gateway. All 3 elements of each
array are in network byte order. Essentially: [(addr, prefix, gateway),
(addr, prefix, gateway), ...] Deprecated: use AddressData and Gateway
-->
<property name="Addresses" type="aau" access="read"/>
<!--
AddressData:
Array of IP address data objects. All addresses will include "address" (an
IP address string), and "prefix" (a uint). Some addresses may include
additional attributes.
-->
<property name="AddressData" type="aa{sv}" access="read"/>
<!--
Gateway:
The gateway in use.
-->
<property name="Gateway" type="s" access="read"/>
<!--
Routes:
Arrays of IPv4 route/prefix/next-hop/metric. All 4 elements of each tuple
are in network byte order. 'route' and 'next hop' are IPv4 addresses,
while prefix and metric are simple unsigned integers. Essentially:
[(route, prefix, next-hop, metric), (route, prefix, next-hop, metric),
...] Deprecated: use RouteData
-->
<property name="Routes" type="aau" access="read"/>
<!--
RouteData:
Array of IP route data objects. All routes will include "dest" (an IP
address string) and "prefix" (a uint). Some routes may include "next-hop"
(an IP address string), "metric" (a uint), and additional attributes.
-->
<property name="RouteData" type="aa{sv}" access="read"/>
<!--
Nameservers:
The nameservers in use. Deprecated: use NameserverData
-->
<property name="Nameservers" type="au" access="read"/>
<!--
NameserverData:
@since: 1.14
The nameservers in use. Currently, only the value "address"
is recognized (with an IP address string).
-->
<property name="NameserverData" type="aa{sv}" access="read"/>
<!--
Domains:
A list of domains this address belongs to.
-->
<property name="Domains" type="as" access="read"/>
<!--
Searches:
A list of dns searches.
-->
<property name="Searches" type="as" access="read"/>
<!--
DnsOptions:
A list of DNS options that modify the behavior of the DNS resolver. See
resolv.conf(5) manual page for the list of supported options.
-->
<property name="DnsOptions" type="as" access="read"/>
<!--
DnsPriority:
The relative priority of DNS servers.
-->
<property name="DnsPriority" type="i" access="read"/>
<!--
WinsServers:
The Windows Internet Name Service servers associated with the connection.
Each address is in network byte order. Deprecated: use WinsServerData
-->
<property name="WinsServers" type="au" access="read"/>
<!--
WinsServerData:
@since: 1.14
The Windows Internet Name Service servers associated with the connection.
-->
<property name="WinsServerData" type="as" access="read"/>
</interface>
</node>
@@ -1,598 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<node name="/org/freedesktop/NetworkManager">
<!--
org.freedesktop.NetworkManager:
@short_description: Connection Manager.
-->
<interface name="org.freedesktop.NetworkManager">
<annotation name="org.gtk.GDBus.C.Name" value="Manager"/>
<!--
Reload:
@flags: Optional flags to specify which parts shall be reloaded.
Reload NetworkManager's configuration and perform certain updates, like flushing a cache or
rewriting external state to disk. This is similar to sending SIGHUP to NetworkManager but it
allows for more fine-grained control over what to reload (see @flags). It also allows
non-root access via PolicyKit and contrary to signals it is synchronous.
No flags (0x00) means to reload everything that is supported which is identical to
sending a SIGHUP.
(0x01) means to reload the NetworkManager.conf configuration from disk. Note that this
does not include connections, which can be reloaded via Setting's ReloadConnections.
(0x02) means to update DNS configuration, which usually involves writing /etc/resolv.conf
anew.
(0x04) means to restart the DNS plugin. This is for example useful when using
dnsmasq plugin, which uses additional configuration in /etc/NetworkManager/dnsmasq.d.
If you edit those files, you can restart the DNS plugin. This action shortly interrupts
name resolution.
Note that flags may affect each other. For example, restarting the DNS plugin (0x04)
implicitly updates DNS too (0x02). Or when reloading the configuration (0x01), changes
to DNS setting also cause a DNS update (0x02). However, (0x01) does not involve restarting
the DNS plugin (0x04) or update resolv.conf (0x02), unless the DNS related configuration
changes in NetworkManager.conf.
-->
<method name="Reload">
<arg name="flags" type="u" direction="in"/>
</method>
<!--
GetDevices:
@devices: List of object paths of network devices known to the system. This list does not include device placeholders (see GetAllDevices()).
Get the list of realized network devices.
-->
<method name="GetDevices">
<arg name="devices" type="ao" direction="out"/>
</method>
<!--
GetAllDevices:
@devices: List of object paths of network devices and device placeholders (eg, devices that do not yet exist but which can be automatically created by NetworkManager if one of their AvailableConnections was activated).
Get the list of all network devices.
-->
<method name="GetAllDevices">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_get_all_devices"/>
<arg name="devices" type="ao" direction="out"/>
</method>
<!--
GetDeviceByIpIface:
@iface: Interface name of the device to find.
@device: Object path of the network device.
Return the object path of the network device referenced by its IP
interface name. Note that some devices (usually modems) only have an IP
interface name when they are connected.
-->
<method name="GetDeviceByIpIface">
<arg name="iface" type="s" direction="in"/>
<arg name="device" type="o" direction="out"/>
</method>
<!--
ActivateConnection:
@connection: The connection to activate. If "/" is given, a valid device path must be given, and NetworkManager picks the best connection to activate for the given device. VPN connections must always pass a valid connection path.
@device: The object path of device to be activated for physical connections. This parameter is ignored for VPN connections, because the specific_object (if provided) specifies the device to use.
@specific_object: The path of a connection-type-specific object this activation should use. This parameter is currently ignored for wired and mobile broadband connections, and the value of "/" should be used (ie, no specific object). For Wi-Fi connections, pass the object path of a specific AP from the card's scan list, or "/" to pick an AP automatically. For VPN connections, pass the object path of an ActiveConnection object that should serve as the "base" connection (to which the VPN connections lifetime will be tied), or pass "/" and NM will automatically use the current default device.
@active_connection: The path of the active connection object representing this active connection.
Activate a connection using the supplied device.
-->
<method name="ActivateConnection">
<arg name="connection" type="o" direction="in"/>
<arg name="device" type="o" direction="in"/>
<arg name="specific_object" type="o" direction="in"/>
<arg name="active_connection" type="o" direction="out"/>
</method>
<!--
AddAndActivateConnection:
@connection: Connection settings and properties; if incomplete missing settings will be automatically completed using the given device and specific object.
@device: The object path of device to be activated using the given connection.
@specific_object: The path of a connection-type-specific object this activation should use. This parameter is currently ignored for wired and mobile broadband connections, and the value of "/" should be used (ie, no specific object). For Wi-Fi connections, pass the object path of a specific AP from the card's scan list, which will be used to complete the details of the newly added connection.
@path: Object path of the new connection that was just added.
@active_connection: The path of the active connection object representing this active connection.
Adds a new connection using the given details (if any) as a template
(automatically filling in missing settings with the capabilities of the
given device and specific object), then activate the new connection.
Cannot be used for VPN connections at this time.
See also AddAndActivateConnection2.
-->
<method name="AddAndActivateConnection">
<arg name="connection" type="a{sa{sv}}" direction="in"/>
<arg name="device" type="o" direction="in"/>
<arg name="specific_object" type="o" direction="in"/>
<arg name="path" type="o" direction="out"/>
<arg name="active_connection" type="o" direction="out"/>
</method>
<!--
AddAndActivateConnection2:
@connection: Connection settings and properties; if incomplete missing settings will be automatically completed using the given device and specific object.
@device: The object path of device to be activated using the given connection.
@specific_object: The path of a connection-type-specific object this activation should use. This parameter is currently ignored for wired and mobile broadband connections, and the value of "/" should be used (ie, no specific object). For Wi-Fi connections, pass the object path of a specific AP from the card's scan list, which will be used to complete the details of the newly added connection.
@options: Further options for the method call.
@path: Object path of the new connection that was just added.
@active_connection: The path of the active connection object representing this active connection.
@result: A dictionary of additional output arguments for future extension. Currently, not additional output arguments are supported.
Adds a new connection using the given details (if any) as a template
(automatically filling in missing settings with the capabilities of the
given device and specific object), then activate the new connection.
Cannot be used for VPN connections at this time.
This method extends AddAndActivateConnection to allow passing further
parameters. At this time the following options are supported:
* persist: A string value of either "disk" (default), "memory" or "volatile". If "memory" is passed, the connection will not be saved to disk. If "volatile" is passed, the connection will not be saved to disk and will be destroyed when disconnected.
* bind-activation: Bind the activation lifetime. Set to "dbus-client" to automatically disconnect when the requesting process disappears from the bus. The default of "none" means the connection is kept activated normally.
-->
<method name="AddAndActivateConnection2">
<arg name="connection" type="a{sa{sv}}" direction="in"/>
<arg name="device" type="o" direction="in"/>
<arg name="specific_object" type="o" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="path" type="o" direction="out"/>
<arg name="active_connection" type="o" direction="out"/>
<arg name="result" type="a{sv}" direction="out"/>
</method>
<!--
DeactivateConnection:
@active_connection: The currently active connection to deactivate.
Deactivate an active connection.
-->
<method name="DeactivateConnection">
<arg name="active_connection" type="o" direction="in"/>
</method>
<!--
Sleep:
@sleep: Indicates whether the NetworkManager daemon should sleep or wake.
Control the NetworkManager daemon's sleep state. When asleep, all
interfaces that it manages are deactivated. When awake, devices are
available to be activated. This command should not be called directly by
users or clients; it is intended for system suspend/resume tracking.
-->
<method name="Sleep">
<arg name="sleep" type="b" direction="in"/>
</method>
<!--
Enable:
@enable: If FALSE, indicates that all networking should be disabled. If TRUE, indicates that NetworkManager should begin managing network devices.
Control whether overall networking is enabled or disabled. When disabled,
all interfaces that NM manages are deactivated. When enabled, all managed
interfaces are re-enabled and available to be activated. This command
should be used by clients that provide to users the ability to
enable/disable all networking.
-->
<method name="Enable">
<arg name="enable" type="b" direction="in"/>
</method>
<!--
GetPermissions:
@permissions: Dictionary of available permissions and results. Each permission is represented by a name (ie "org.freedesktop.NetworkManager.Foobar") and each result is one of the following values: "yes" (the permission is available), "auth" (the permission is available after a successful authentication), or "no" (the permission is denied). Clients may use these values in the UI to indicate the ability to perform certain operations.
Returns the permissions a caller has for various authenticated operations
that NetworkManager provides, like Enable/Disable networking, changing
Wi-Fi, WWAN, and WiMAX state, etc.
-->
<method name="GetPermissions">
<arg name="permissions" type="a{ss}" direction="out"/>
</method>
<!--
CheckPermissions:
Emitted when system authorization details change, indicating that clients
may wish to recheck permissions with GetPermissions.
-->
<signal name="CheckPermissions"/>
<!--
SetLogging:
@level: One of [ERR, WARN, INFO, DEBUG, TRACE, OFF, KEEP]. This level is applied to the domains as specified in the domains argument. Except for the special level "KEEP", all unmentioned domains are disabled entirely. "KEEP" is special and allows not to change the current setting except for the specified domains. E.g. level=KEEP and domains=PLATFORM:DEBUG will only touch the platform domain.
@domains: A combination of logging domains separated by commas (','), or "NONE" to disable logging. Each domain enables logging for operations related to that domain. Available domains are: [PLATFORM, RFKILL, ETHER, WIFI, BT, MB, DHCP4, DHCP6, PPP, WIFI_SCAN, IP4, IP6, AUTOIP4, DNS, VPN, SHARING, SUPPLICANT, AGENTS, SETTINGS, SUSPEND, CORE, DEVICE, OLPC, WIMAX, INFINIBAND, FIREWALL, ADSL, BOND, VLAN, BRIDGE, DBUS_PROPS, TEAM, CONCHECK, DCB, DISPATCH, AUDIT]. In addition to these domains, the following special domains can be used: [NONE, ALL, DEFAULT, DHCP, IP]. You can also specify that some domains should log at a different level from the default by appending a colon (':') and a log level (eg, 'WIFI:DEBUG'). If an empty string is given, the log level is changed but the current set of log domains remains unchanged.
Set logging verbosity and which operations are logged.
-->
<method name="SetLogging">
<arg name="level" type="s" direction="in"/>
<arg name="domains" type="s" direction="in"/>
</method>
<!--
GetLogging:
@level: One of [ERR, WARN, INFO, DEBUG, TRACE].
@domains: For available domains see SetLogging() call.
Get current logging verbosity level and operations domains.
-->
<method name="GetLogging">
<arg name="level" type="s" direction="out"/>
<arg name="domains" type="s" direction="out"/>
</method>
<!--
CheckConnectivity:
@connectivity: (<link linkend="NMConnectivityState">NMConnectivityState</link>) The current connectivity state.
Re-check the network connectivity state.
-->
<method name="CheckConnectivity">
<arg name="connectivity" type="u" direction="out"/>
</method>
<!--
state:
@state: <link linkend="NMState">NMState</link>
The overall networking state as determined by the NetworkManager daemon,
based on the state of network devices under its management.
-->
<method name="state">
<arg name="state" type="u" direction="out"/>
</method>
<!--
CheckpointCreate:
@devices: A list of device paths for which a checkpoint should be created. An empty list means all devices.
@rollback_timeout: The time in seconds until NetworkManager will automatically rollback to the checkpoint. Set to zero for infinite.
@flags: (<link linkend="NMCheckpointCreateFlags">NMCheckpointCreateFlags</link>) Flags for the creation.
@checkpoint: On success, the path of the new checkpoint.
Create a checkpoint of the current networking configuration
for given interfaces. If @rollback_timeout is not zero, a
rollback is automatically performed after the given timeout.
-->
<method name="CheckpointCreate">
<arg name="devices" type="ao" direction="in"/>
<arg name="rollback_timeout" type="u" direction="in"/>
<arg name="flags" type="u" direction="in"/>
<arg name="checkpoint" type="o" direction="out"/>
</method>
<!--
CheckpointDestroy:
@checkpoint: The checkpoint to be destroyed. Set to empty to cancel all pending checkpoints.
Destroy a previously created checkpoint.
-->
<method name="CheckpointDestroy">
<arg name="checkpoint" type="o" direction="in"/>
</method>
<!--
CheckpointRollback:
@checkpoint: The checkpoint to be rolled back.
@result: On return, a dictionary of devices and results. Devices are represented by their original D-Bus path; each result is a <link linkend="NMRollbackResult">RollbackResult</link>.
Rollback a checkpoint before the timeout is reached.
-->
<method name="CheckpointRollback">
<arg name="checkpoint" type="o" direction="in"/>
<arg name="result" type="a{su}" direction="out" />
</method>
<!--
CheckpointAdjustRollbackTimeout:
@checkpoint: The checkpoint to be rolled back.
@add_timeout: Number of seconds from <emphasis>now</emphasis> in which the timeout will expire. Set to 0 to disable the timeout.
@since: 1.12
Reset the timeout for rollback for the checkpoint.
Note that the added seconds start counting from now,
not "Created" timestamp or the previous expiration
time. Note that the "Created" property of the checkpoint
will stay unchanged by this call. However, the "RollbackTimeout"
will be recalculated to give the approximate new expiration time.
The new "RollbackTimeout" property will be approximate up to
one second precision, which is the accuracy of the property.
-->
<method name="CheckpointAdjustRollbackTimeout">
<arg name="checkpoint" type="o" direction="in"/>
<arg name="add_timeout" type="u" direction="in"/>
</method>
<!--
Devices:
The list of realized network devices. Realized devices are those which
have backing resources (eg from the kernel or a management daemon like
ModemManager, teamd, etc).
-->
<property name="Devices" type="ao" access="read"/>
<!--
AllDevices:
The list of both realized and un-realized network devices. Un-realized
devices are software devices which do not yet have backing resources, but
for which backing resources can be created if the device is activated.
-->
<property name="AllDevices" type="ao" access="read"/>
<!--
Checkpoints:
The list of active checkpoints.
-->
<property name="Checkpoints" type="ao" access="read"/>
<!--
NetworkingEnabled:
Indicates if overall networking is currently enabled or not. See the
Enable() method.
-->
<property name="NetworkingEnabled" type="b" access="read"/>
<!--
WirelessEnabled:
Indicates if wireless is currently enabled or not.
-->
<property name="WirelessEnabled" type="b" access="readwrite"/>
<!--
WirelessHardwareEnabled:
Indicates if the wireless hardware is currently enabled, i.e. the state of
the RF kill switch.
-->
<property name="WirelessHardwareEnabled" type="b" access="read"/>
<!--
WwanEnabled:
Indicates if mobile broadband devices are currently enabled or not.
-->
<property name="WwanEnabled" type="b" access="readwrite"/>
<!--
WwanHardwareEnabled:
Indicates if the mobile broadband hardware is currently enabled, i.e. the
state of the RF kill switch.
-->
<property name="WwanHardwareEnabled" type="b" access="read"/>
<!--
WimaxEnabled:
DEPRECATED. Doesn't have any meaning and is around only for
compatibility reasons.
-->
<property name="WimaxEnabled" type="b" access="readwrite"/>
<!--
WimaxHardwareEnabled:
DEPRECATED. Doesn't have any meaning and is around only for
compatibility reasons.
-->
<property name="WimaxHardwareEnabled" type="b" access="read"/>
<!--
RadioFlags:
@since: 1.38
Flags related to radio devices. See <link
linkend="NMRadioFlags">NMRadioFlags</link> for the list of flags
supported.
-->
<property name="RadioFlags" type="u" access="read"/>
<!--
ActiveConnections:
List of active connection object paths.
-->
<property name="ActiveConnections" type="ao" access="read"/>
<!--
PrimaryConnection:
The object path of the "primary" active connection being used to access
the network. In particular, if there is no VPN active, or the VPN does not
have the default route, then this indicates the connection that has the
default route. If there is a VPN active with the default route, then this
indicates the connection that contains the route to the VPN endpoint.
-->
<property name="PrimaryConnection" type="o" access="read"/>
<!--
PrimaryConnectionType:
The connection type of the "primary" active connection being used to
access the network. This is the same as the Type property on the object
indicated by PrimaryConnection.
-->
<property name="PrimaryConnectionType" type="s" access="read"/>
<!--
Metered:
Indicates whether the connectivity is metered. This is equivalent to the
metered property of the device associated with the primary connection.
Returns: <link linkend="NMMetered">NMMetered</link>
-->
<property name="Metered" type="u" access="read"/>
<!--
ActivatingConnection:
The object path of an active connection that is currently being activated
and which is expected to become the new PrimaryConnection when it finishes
activating.
-->
<property name="ActivatingConnection" type="o" access="read"/>
<!--
Startup:
Indicates whether NM is still starting up; this becomes FALSE when NM has
finished attempting to activate every connection that it might be able to
activate at startup.
-->
<property name="Startup" type="b" access="read"/>
<!--
Version:
NetworkManager version.
-->
<property name="Version" type="s" access="read"/>
<!--
VersionInfo:
NetworkManager version and capabilities.
The first element in the array is the NM_VERSION of the daemon. It is a binary representation
of the "Version" and can be compared numerically. The version is encoded as
"(major &lt;&lt; 16 | minor &lt;&lt; 8 | micro)".
The following elements are a bitfield of static capabilities of the daemon. See
#NMVersionInfoCapability for the available capability numbers.
Since: 1.42
-->
<property name="VersionInfo" type="au" access="read"/>
<!--
Capabilities:
The current set of capabilities. See <link
linkend="NMCapability">NMCapability</link> for currently
defined capability numbers. The array is guaranteed to
be sorted in ascending order without duplicates.
-->
<property name="Capabilities" type="au" access="read"/>
<!--
State:
The overall state of the NetworkManager daemon.
This takes state of all active connections and the connectivity state into account
to produce a single indicator of the network accessibility status.
The graphical shells may use this property to provide network connection status
indication and applications may use this to check if Internet connection is
accessible. Shell that is able to cope with captive portals should use the
"Connectivity" property to decide whether to present a captive portal authentication
dialog.
Returns: <link linkend="NMState">NMState</link>
-->
<property name="State" type="u" access="read"/>
<!--
StateChanged:
@state: (<link linkend="NMState">NMState</link>) The new state of NetworkManager.
NetworkManager's state changed.
-->
<signal name="StateChanged">
<arg name="state" type="u"/>
</signal>
<!--
Connectivity:
The result of the last connectivity check. The connectivity check is triggered
automatically when a default connection becomes available, periodically and by
calling a CheckConnectivity() method.
This property is in general useful for the graphical shell to determine whether
the Internet access is being hijacked by an authentication gateway (a "captive
portal"). In such case it would typically present a web browser window to give
the user a chance to authenticate and call CheckConnectivity() when the user
submits a form or dismisses the window.
To determine the whether the user is able to access the Internet without dealing
with captive portals (e.g. to provide a network connection indicator or disable
controls that require Internet access), the "State" property is more suitable.
Returns: <link linkend="NMConnectivityState">NMConnectivityState</link>
-->
<property name="Connectivity" type="u" access="read"/>
<!--
ConnectivityCheckAvailable:
Indicates whether connectivity checking service has been
configured. This may return true even if the service is not
currently enabled.
This is primarily intended for use in a privacy control panel,
as a way to determine whether to show an option to
enable/disable the feature.
-->
<property name="ConnectivityCheckAvailable" type="b" access="read"/>
<!--
ConnectivityCheckEnabled:
Indicates whether connectivity checking is enabled. This
property can also be written to disable connectivity
checking (as a privacy control panel might want to do).
-->
<property name="ConnectivityCheckEnabled" type="b" access="readwrite"/>
<!--
ConnectivityCheckUri:
The URI that NetworkManager will hit to check if there is internet connectivity.
-->
<property name="ConnectivityCheckUri" type="s" access="read"/>
<!--
GlobalDnsConfiguration:
Dictionary of global DNS settings where the key is one of "searches",
"options" and "domains". The values for the "searches" and "options" keys
are string arrays describing the list of search domains and resolver
options, respectively. The value of the "domains" key is a second-level
dictionary, where each key is a domain name, and each key's value is a
third-level dictionary with the keys "servers" and "options". "servers" is
a string array of DNS servers, "options" is a string array of
domain-specific options.
-->
<property name="GlobalDnsConfiguration" type="a{sv}" access="readwrite"/>
<!--
DeviceAdded:
@device_path: The object path of the newly added device.
A device was added to the system
-->
<signal name="DeviceAdded">
<arg name="device_path" type="o"/>
</signal>
<!--
DeviceRemoved:
@device_path: The object path of the device that was just removed.
A device was removed from the system, and is no longer available.
-->
<signal name="DeviceRemoved">
<arg name="device_path" type="o"/>
</signal>
</interface>
</node>
@@ -1,93 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
namespace networkmanager {
std::unique_ptr<ActiveConnection>
ObjectManager::GetActiveConnectionForAccessPoint(
const sdbus::ObjectPath &access_point,
const sdbus::ObjectPath &device_path) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/") ==
0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
if (specific_object == access_point) {
std::vector<sdbus::ObjectPath> devices = props["Devices"];
for (auto &path : devices) {
if (path == device_path) {
return std::make_unique<ActiveConnection>(
system_bus_, object_path);
}
}
}
}
}
}
return nullptr;
}
std::unique_ptr<IP4Config> ObjectManager::GetIp4Config(
const sdbus::ObjectPath &active_connection) {
std::map<sdbus::ObjectPath,
std::map<std::string, std::map<std::string, sdbus::Variant>>>
objects;
try {
objects = GetManagedObjects();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "GetManagedObjects", e);
return nullptr;
}
for (auto &[object_path, interfaces] : objects) {
if (object_path.find("/org/freedesktop/NetworkManager/ActiveConnection/",
0) == 0) {
if (interfaces.count(org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME) == 1) {
auto props = interfaces[org::freedesktop::NetworkManager::Connection::
Active_proxy::INTERFACE_NAME];
sdbus::ObjectPath specific_object = props["SpecificObject"];
if (specific_object == active_connection) {
sdbus::ObjectPath ip4config = props["Ip4Config"];
return std::make_unique<IP4Config>(system_bus_, ip4config);
}
}
}
}
return nullptr;
}
} // namespace networkmanager
} // namespace linux
} // namespace nearby
@@ -1,183 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_H_
#include <atomic>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/ip4config_client.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/networkmanager_client.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
namespace networkmanager {
class NetworkManager final
: public sdbus::ProxyInterfaces<org::freedesktop::NetworkManager_proxy> {
public:
NetworkManager(const NetworkManager &) = delete;
NetworkManager(NetworkManager &&) = delete;
NetworkManager &operator=(const NetworkManager &) = delete;
NetworkManager &operator=(NetworkManager &&) = delete;
explicit NetworkManager(std::shared_ptr<sdbus::IConnection> system_bus)
: ProxyInterfaces(*system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop/NetworkManager"),
system_bus_(std::move(system_bus)),
state_(kNMStateUnknown) {
registerProxy();
try {
setState(State());
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
~NetworkManager() { unregisterProxy(); }
// https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMState
enum NMState {
kNMStateUnknown = 0,
kNMStateAsleep = 10,
kNMStateDisconnected = 20,
kNMStateDisconnecting = 30,
kNMStateConnecting = 40,
kNMStateConnectedLocal = 50,
kNMStateConnectedSite = 60,
kNMStateConnectedGlobal = 70,
};
NMState getState() const { return state_; }
std::shared_ptr<sdbus::IConnection> GetConnection() { return system_bus_; }
protected:
void onCheckPermissions() override {}
void onStateChanged(const uint32_t &state) override { setState(state); }
void onDeviceAdded(const sdbus::ObjectPath &device_path) override {}
void onDeviceRemoved(const sdbus::ObjectPath &device_path) override {}
private:
void inline setState(std::uint32_t val) {
#define NM_STATE_CASE_SET(k) \
case (k): \
state_ = (k); \
break
switch (val) {
NM_STATE_CASE_SET(kNMStateAsleep);
NM_STATE_CASE_SET(kNMStateDisconnected);
NM_STATE_CASE_SET(kNMStateDisconnecting);
NM_STATE_CASE_SET(kNMStateConnecting);
NM_STATE_CASE_SET(kNMStateConnectedLocal);
NM_STATE_CASE_SET(kNMStateConnectedSite);
NM_STATE_CASE_SET(kNMStateConnectedGlobal);
default:
LOG(ERROR) << __func__ << "invalid NMState value: " << val
<< ", setting state to unknown";
NM_STATE_CASE_SET(kNMStateUnknown);
}
#undef NM_STATE_CASE_SET
};
std::shared_ptr<sdbus::IConnection> system_bus_;
std::atomic<NMState> state_;
};
class IP4Config : public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::IP4Config_proxy> {
public:
IP4Config(const IP4Config &) = delete;
IP4Config(IP4Config &&) = delete;
IP4Config &operator=(const IP4Config &) = delete;
IP4Config &operator=(IP4Config &&) = delete;
IP4Config(std::shared_ptr<sdbus::IConnection> system_bus,
const sdbus::ObjectPath &config_object_path)
: ProxyInterfaces(*system_bus, "org.freedesktop.NetworkManager",
config_object_path),
system_bus_(std::move(system_bus)) {
registerProxy();
}
~IP4Config() { unregisterProxy(); }
private:
std::shared_ptr<sdbus::IConnection> system_bus_;
};
class ObjectManager final
: public sdbus::ProxyInterfaces<sdbus::ObjectManager_proxy> {
public:
ObjectManager(const ObjectManager &) = delete;
ObjectManager(ObjectManager &&) = delete;
ObjectManager &operator=(const ObjectManager &) = delete;
ObjectManager &operator=(ObjectManager &&) = delete;
explicit ObjectManager(std::shared_ptr<sdbus::IConnection> system_bus)
: ProxyInterfaces(*system_bus, "org.freedesktop.NetworkManager",
"/org/freedesktop"),
system_bus_(std::move(system_bus)) {
registerProxy();
}
~ObjectManager() { unregisterProxy(); }
std::unique_ptr<IP4Config> GetIp4Config(
const sdbus::ObjectPath &access_point);
std::unique_ptr<ActiveConnection> GetActiveConnectionForAccessPoint(
const sdbus::ObjectPath &access_point_path,
const sdbus::ObjectPath &device_path);
protected:
void onInterfacesAdded(
const sdbus::ObjectPath &objectPath,
const std::map<std::string, std::map<std::string, sdbus::Variant>>
&interfacesAndProperties) override {}
void onInterfacesRemoved(
const sdbus::ObjectPath &objectPath,
const std::vector<std::string> &interfaces) override {}
private:
std::shared_ptr<sdbus::IConnection> system_bus_;
};
namespace constants {
// Indicates the 802.11 mode an access point or device is currently in.
enum NM80211Mode {
kNM80211ModeUnknown = 0,
kNM80211ModeAdHoc = 1,
kNM80211ModeInfra = 2,
kNM80211ModeAP = 3,
kNM80211ModeMesh = 4,
};
const int32_t kNMTernaryDefault = -1;
const int32_t kNMTernaryFalse = 0;
const int32_t kNMTernaryTrue = 1;
namespace setting {
const int32_t kWirelessSecurityPMFDefaut = 0;
const int32_t kWirelessSecurityPMFDisable = 1;
const int32_t kWirelessSecurityPMFOptional = 2;
const int32_t kWirelessSecurityPMFRequired = 3;
const int32_t kIP6ConfigAddrGenModeEUI64 = 0;
const int32_t kIP6ConfigAddrGenModeStablePrivacy = 1;
const int32_t kIP6ConfigAddrGenModeDefaultOrEUI64 = 2;
const int32_t kIP6ConfigAddrGenModeDefault = 3;
} // namespace setting
} // namespace constants
} // namespace networkmanager
} // namespace linux
} // namespace nearby
#endif
@@ -1,43 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACCESS_POINT_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACCESS_POINT_H_
#include <sdbus-c++/ProxyInterfaces.h>
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/access_point_client.h"
namespace nearby {
namespace linux {
class NetworkManagerAccessPoint
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::AccessPoint_proxy> {
public:
NetworkManagerAccessPoint(const NetworkManagerAccessPoint &) = delete;
NetworkManagerAccessPoint(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint &operator=(const NetworkManagerAccessPoint &) =
delete;
NetworkManagerAccessPoint &operator=(NetworkManagerAccessPoint &&) = delete;
NetworkManagerAccessPoint(sdbus::IConnection &system_bus,
sdbus::ObjectPath access_point_object_path)
: ProxyInterfaces(system_bus, "org.freedesktop.NetworkManager",
std::move(access_point_object_path)) {
registerProxy();
}
~NetworkManagerAccessPoint() { unregisterProxy(); }
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,130 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <map>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
namespace nearby {
namespace linux {
namespace networkmanager {
std::string ActiveConnection::ActiveConnectionStateReason::ToString() const {
switch (value) {
case ActiveConnection::ActiveConnectionStateReason::kStateReasonUnknown:
return "The reason for the active connection state change is "
"unknown.";
case ActiveConnection::ActiveConnectionStateReason::kStateReasonNone:
return "No reason was given for the active connection state change.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonUserDisconnected:
return "The active connection changed state because the user "
"disconnected it.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonDeviceDisconnected:
return "The active connection changed state because the "
"device it was "
"using was disconnected.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonServiceStopped:
return "The service providing the VPN connection was stopped.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonIPConfigInvalid:
return "The IP config of the active connection was invalid.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonConnectTimeout:
return "The connection attempt to the VPN service timed out.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonServiceStartTimeout:
return "A timeout occurred while starting the service providing the "
"VPN connection.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonServiceStartFailed:
return "Starting the service providing the VPN connection failed.";
case ActiveConnection::ActiveConnectionStateReason::kStateReasonNoSecrets:
return "Necessary secrets for the connection were not provided.";
case ActiveConnection::ActiveConnectionStateReason::kStateReasonLoginFailed:
return "Authentication to the server failed.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonConnectionRemoved:
return "The connection was deleted from settings.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonDependencyFailed:
return "Master connection of this connection failed to activate.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonDeviceRealizeFailed:
return "Could not create the software device link.";
case ActiveConnection::ActiveConnectionStateReason::
kStateReasonDeviceRemoved:
return "The device this connection depended on disappeared.";
}
}
std::vector<std::string> ActiveConnection::GetIP4Addresses() {
sdbus::ObjectPath ip4config_path;
try {
ip4config_path = Ip4Config();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "Ip4Config", e);
return {};
}
IP4Config ip4config(system_bus_, ip4config_path);
std::vector<std::map<std::string, sdbus::Variant>> address_data;
try {
address_data = ip4config.AddressData();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "AddressData", e);
return {};
}
std::vector<std::string> ip4addresses;
for (auto &data : address_data) {
if (data.count("address") == 1) {
ip4addresses.push_back(data["address"]);
}
}
return ip4addresses;
}
std::pair<std::optional<ActiveConnection::ActiveConnectionStateReason>, bool>
ActiveConnection::WaitForConnection(absl::Duration timeout) {
LOG(INFO) << __func__ << ": Waiting for an update to "
<< getObjectPath() << "'s state";
auto state_changed = [this]() {
this->state_mutex_.AssertReaderHeld();
return this->state_ == kStateActivated || this->state_ == kStateDeactivated;
};
absl::Condition cond(&state_changed);
auto success = state_mutex_.ReaderLockWhenWithTimeout(cond, timeout);
auto reason = reason_;
auto state = state_;
state_mutex_.ReaderUnlock();
if (!success) {
return {reason, true};
}
return state == kStateActivated ? std::pair{std::nullopt, false}
: std::pair{std::optional(reason), false};
}
} // namespace networkmanager
} // namespace linux
} // namespace nearby
@@ -1,125 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACTIVE_CONNECTION_H_
#define PLATFORM_IMPL_LINUX_NETWORK_MANAGER_ACTIVE_CONNECTION_H_
#include <ostream>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/connection_active_client.h"
namespace nearby {
namespace linux {
namespace networkmanager {
class ActiveConnection
: public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::Connection::Active_proxy> {
public:
enum ActiveConnectionState {
kStateUnknown = 0,
kStateActivating = 1,
kStateActivated = 2,
kStateDeactivating = 3,
kStateDeactivated = 4
};
struct ActiveConnectionStateReason {
enum Value {
kStateReasonUnknown = 0,
kStateReasonNone = 1,
kStateReasonUserDisconnected = 2,
kStateReasonDeviceDisconnected = 3,
kStateReasonServiceStopped = 4,
kStateReasonIPConfigInvalid = 5,
kStateReasonConnectTimeout = 6,
kStateReasonServiceStartTimeout = 7,
kStateReasonServiceStartFailed = 8,
kStateReasonNoSecrets = 9,
kStateReasonLoginFailed = 10,
kStateReasonConnectionRemoved = 11,
kStateReasonDependencyFailed = 12,
kStateReasonDeviceRealizeFailed = 13,
kStateReasonDeviceRemoved = 14,
};
Value value{kStateReasonUnknown};
std::string ToString() const;
};
ActiveConnection(const ActiveConnection &) = delete;
ActiveConnection(ActiveConnection &&) = delete;
ActiveConnection &operator=(const ActiveConnection &) = delete;
ActiveConnection &operator=(ActiveConnection &&) = delete;
explicit ActiveConnection(std::shared_ptr<sdbus::IConnection> system_bus,
sdbus::ObjectPath active_connection_path)
: ProxyInterfaces(*system_bus, "org.freedesktop.NetworkManager",
std::move(active_connection_path)),
system_bus_(std::move(system_bus)),
state_(kStateUnknown),
reason_{ActiveConnection::ActiveConnectionStateReason::
kStateReasonUnknown} {
registerProxy();
try {
auto state = State();
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "State", e);
}
}
virtual ~ActiveConnection() { unregisterProxy(); }
protected:
void onStateChanged(const uint32_t &state, const uint32_t &reason) override
ABSL_LOCKS_EXCLUDED(state_mutex_) {
absl::MutexLock l(&state_mutex_);
if (state >= kStateUnknown && state <= kStateDeactivated) {
state_ = static_cast<ActiveConnectionState>(state);
}
if (reason >= ActiveConnection::ActiveConnectionStateReason::
kStateReasonUnknown &&
reason <= ActiveConnection::ActiveConnectionStateReason::
kStateReasonDeviceRemoved) {
reason_ = ActiveConnectionStateReason{
static_cast<ActiveConnectionStateReason::Value>(reason)};
}
}
public:
std::pair<std::optional<ActiveConnectionStateReason>, bool> WaitForConnection(
absl::Duration timeout = absl::Seconds(10))
ABSL_LOCKS_EXCLUDED(state_mutex_);
std::vector<std::string> GetIP4Addresses();
private:
std::shared_ptr<sdbus::IConnection> system_bus_;
absl::Mutex state_mutex_;
ActiveConnectionState state_ ABSL_GUARDED_BY(state_mutex_);
ActiveConnectionStateReason reason_ ABSL_GUARDED_BY(state_mutex_);
};
extern std::ostream &operator<<(
std::ostream &stream,
const ActiveConnection::ActiveConnectionStateReason &reason);
} // namespace networkmanager
} // namespace linux
} // namespace nearby
#endif
@@ -29,7 +29,6 @@
#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_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"
@@ -40,10 +39,6 @@
#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 "absl/strings/str_cat.h"
@@ -51,8 +46,6 @@
#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 "scheduled_executor.h"
@@ -245,55 +238,8 @@ std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
std::unique_ptr<api::ble_v2::BleMedium>
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter &adapter) {
return nullptr;
// TODO: Enable BLEv2 once BlueZ support is added.
// return std::make_unique<linux::BleV2Medium>(
// dynamic_cast<linux::BluetoothAdapter &>(adapter));
}
namespace {
// static std::unique_ptr<linux::NetworkManagerWifiMedium> createWifiMedium(
// std::shared_ptr<linux::networkmanager::NetworkManager> nm) {
// return nullptr;
// std::vector<sdbus::ObjectPath> 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::networkmanager::ObjectManager(nm->GetConnection());
//
// std::map<sdbus::ObjectPath,
// std::map<std::string, std::map<std::string, sdbus::Variant>>>
// 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) {
// LOG(INFO) << __func__
// << ": Found a wireless device at :" << device_path;
// return std::make_unique<linux::NetworkManagerWifiMedium>(nm,
// device_path);
// }
// }
// }
//
// LOG(ERROR) << __func__
// << ": couldn't find a wireless device on this system";
// return nullptr;
// }
} // namespace
std::unique_ptr<api::WifiMedium> ImplementationPlatform::CreateWifiMedium() {
return nullptr;
// auto nm =
@@ -1,173 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_TCP_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_TCP_SERVER_SOCKET_H_
#include <arpa/inet.h>
#include <netinet/in.h>
#include <atomic>
#include <functional>
#include <sdbus-c++/Types.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/stream.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
class TCPSocket {
public:
explicit TCPSocket(const sdbus::UnixFd& fd)
: closed_(false), output_stream_(fd), input_stream_(fd) {}
static std::optional<TCPSocket> Connect(const std::string& ip_address,
int port) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOG(ERROR) << __func__
<< ": Error opening socket: " << std::strerror(errno);
return std::nullopt;
}
LOG(INFO) << __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<struct sockaddr*>(&addr), sizeof(addr));
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error connecting to socket: "
<< std::strerror(errno);
return std::nullopt;
}
return TCPSocket(sdbus::UnixFd(sock));
}
InputStream& GetInputStream() { return input_stream_; }
OutputStream& GetOutputStream() { return output_stream_; }
Exception Close() {
if (closed_) return {Exception::kFailed};
closed_ = true;
input_stream_.Close();
output_stream_.Close();
return {Exception::kSuccess};
};
private:
bool closed_;
OutputStream output_stream_;
InputStream input_stream_;
};
class TCPServerSocket {
public:
explicit TCPServerSocket(int fd) : fd_(fd) {}
static std::optional<TCPServerSocket> Listen(
std::optional<const std::reference_wrapper<std::string>> ip_address,
int port) {
auto sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOG(ERROR) << __func__
<< ": Error opening socket: " << std::strerror(errno);
return std::nullopt;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (ip_address.has_value())
addr.sin_addr.s_addr = inet_addr(ip_address->get().c_str());
else
addr.sin_addr.s_addr = htonl(INADDR_ANY);
auto ret =
bind(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error binding to socket: "
<< std::strerror(errno);
return std::nullopt;
}
ret = listen(sock, 0);
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error listening on socket: "
<< std::strerror(errno);
return std::nullopt;
}
return TCPServerSocket(sock);
}
std::optional<TCPSocket> Accept() {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
auto conn =
accept(fd_.get(), reinterpret_cast<struct sockaddr*>(&addr), &len);
if (conn < 0) {
LOG(ERROR) << __func__
<< ": Error accepting incoming connections on socket "
<< fd_.get() << ": " << std::strerror(errno);
return std::nullopt;
}
return TCPSocket(sdbus::UnixFd(conn));
};
Exception Close() {
int fd = fd_.release();
shutdown(fd, SHUT_RDWR);
auto ret = close(fd);
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error closing socket " << fd << ": "
<< std::strerror(errno);
return {Exception::kFailed};
}
return {Exception::kSuccess};
};
int GetPort() const {
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
auto ret =
getsockname(fd_.get(), reinterpret_cast<struct sockaddr*>(&sin), &len);
if (ret < 0) {
LOG(ERROR) << __func__
<< ": Error getting information for socket "
<< fd_.get() << ": " << std::strerror(errno);
return 0;
}
return ntohs(sin.sin_port);
}
private:
sdbus::UnixFd fd_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,137 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <memory>
#include "internal/platform/implementation/linux/tcp_server_socket.h"
#include "internal/platform/implementation/linux/wifi_direct.h"
#include "internal/platform/implementation/linux/wifi_direct_server_socket.h"
#include "internal/platform/implementation/linux/wifi_direct_socket.h"
#include "internal/platform/implementation/linux/wifi_hotspot.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
#include "internal/platform/wifi_credential.h"
namespace nearby {
namespace linux {
std::unique_ptr<api::WifiDirectSocket>
NetworkManagerWifiDirectMedium::ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) {
auto socket = TCPSocket::Connect(std::string(ip_address), port);
if (!socket.has_value()) return nullptr;
return std::make_unique<WifiDirectSocket>(std::move(*socket));
}
std::unique_ptr<api::WifiDirectServerSocket>
NetworkManagerWifiDirectMedium::ListenForService(int port) {
auto active_connection = wireless_device_->GetActiveConnection();
if (active_connection == nullptr) {
return nullptr;
}
auto ip4addresses = active_connection->GetIP4Addresses();
if (ip4addresses.empty()) {
LOG(ERROR)
<< __func__
<< "Could not find any IPv4 addresses for active connection "
<< active_connection->getObjectPath();
return nullptr;
}
auto socket = TCPServerSocket::Listen(std::ref(ip4addresses[0]), port);
if (!socket.has_value()) return nullptr;
return std::make_unique<NetworkManagerWifiDirectServerSocket>(
std::move(*socket), std::move(active_connection), network_manager_);
}
bool NetworkManagerWifiDirectMedium::ConnectWifiDirect(
WifiDirectCredentials *wifi_direct_credentials) {
if (wifi_direct_credentials == nullptr) {
LOG(ERROR) << __func__ << ": hotspot_credentials cannot be null";
return false;
}
auto ssid = wifi_direct_credentials->GetSSID();
auto password = wifi_direct_credentials->GetPassword();
return wireless_device_->ConnectToNetwork(ssid, password,
api::WifiAuthType::kWpaPsk) ==
api::WifiConnectionStatus::kConnected;
}
bool NetworkManagerWifiDirectMedium::DisconnectWifiDirect() {
if (!ConnectedToWifi()) {
LOG(ERROR) << __func__ << ": Not connected to a WiFi hotspot";
return false;
}
auto active_connection = wireless_device_->GetActiveConnection();
if (active_connection == nullptr) {
return false;
}
try {
network_manager_->DeactivateConnection(active_connection->getObjectPath());
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactivateConnection", e);
return false;
}
return true;
}
bool NetworkManagerWifiDirectMedium::ConnectedToWifi() {
try {
auto mode = wireless_device_->Mode();
return mode == 2; // NM_802_11_MODE_INFRA
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
return false;
}
}
bool NetworkManagerWifiDirectMedium::StartWifiDirect(
WifiDirectCredentials *wifi_direct_credentials) {
// According to the comments in the windows implementation, the wifi direct
// medium is currently just a regular wifi hotspot.
auto wireless_device = std::make_unique<NetworkManagerWifiMedium>(
network_manager_, wireless_device_->getObjectPath());
auto hotspot = NetworkManagerWifiHotspotMedium(network_manager_,
std::move(wireless_device));
HotspotCredentials hotspot_creds;
if (!hotspot.StartWifiHotspot(&hotspot_creds)) return false;
wifi_direct_credentials->SetSSID(hotspot_creds.GetSSID());
wifi_direct_credentials->SetPassword(hotspot_creds.GetPassword());
return true;
}
bool NetworkManagerWifiDirectMedium::StopWifiDirect() {
auto wireless_device = std::make_unique<NetworkManagerWifiMedium>(
network_manager_, wireless_device_->getObjectPath());
auto hotspot = NetworkManagerWifiHotspotMedium(network_manager_,
std::move(wireless_device));
return hotspot.DisconnectWifiHotspot();
}
} // namespace linux
} // namespace nearby
@@ -1,66 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_H_
#include <memory>
#include <optional>
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiDirectMedium : public api::WifiDirectMedium {
public:
NetworkManagerWifiDirectMedium(
std::shared_ptr<networkmanager::NetworkManager> network_manager,
std::unique_ptr<NetworkManagerWifiMedium> wireless_device)
: system_bus_(network_manager->GetConnection()),
network_manager_(std::move(network_manager)),
wireless_device_(std::move(wireless_device)) {}
bool IsInterfaceValid() const override { return true; }
std::unique_ptr<api::WifiDirectSocket> ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) override;
std::unique_ptr<api::WifiDirectServerSocket> ListenForService(
int port) override;
bool ConnectWifiDirect(
WifiDirectCredentials *wifi_direct_credentials) override;
bool DisconnectWifiDirect() override;
bool StartWifiDirect(WifiDirectCredentials *wifi_direct_credentials) override;
bool StopWifiDirect() override;
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange()
override {
return std::nullopt;
}
private:
bool ConnectedToWifi();
std::shared_ptr<sdbus::IConnection> system_bus_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,51 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <netinet/in.h>
#include <sys/socket.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/wifi_direct_server_socket.h"
#include "internal/platform/implementation/linux/wifi_direct_socket.h"
namespace nearby {
namespace linux {
std::string NetworkManagerWifiDirectServerSocket::GetIPAddress() const {
auto ip4addresses = active_conn_->GetIP4Addresses();
if (ip4addresses.empty()) {
LOG(ERROR)
<< __func__
<< ": Could not find any IPv4 addresses for active connection "
<< active_conn_->getObjectPath();
return std::string();
}
return ip4addresses[0];
}
int NetworkManagerWifiDirectServerSocket::GetPort() const {
return server_socket_.GetPort();
}
std::unique_ptr<api::WifiDirectSocket>
NetworkManagerWifiDirectServerSocket::Accept() {
auto sock = server_socket_.Accept();
if (!sock.has_value()) return nullptr;
return std::make_unique<WifiDirectSocket>(std::move(*sock));
}
Exception NetworkManagerWifiDirectServerSocket::Close() {
return server_socket_.Close();
}
} // namespace linux
} // namespace nearby
@@ -1,49 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_SERVER_SOCKET_H_
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/linux/tcp_server_socket.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_direct.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiDirectServerSocket
: public api::WifiDirectServerSocket {
public:
NetworkManagerWifiDirectServerSocket(
TCPServerSocket socket,
std::unique_ptr<networkmanager::ActiveConnection> active_conn,
std::shared_ptr<networkmanager::NetworkManager> network_manager)
: server_socket_(std::move(socket)),
active_conn_(std::move(active_conn)),
network_manager_(std::move(network_manager)) {}
std::string GetIPAddress() const override;
int GetPort() const override;
std::unique_ptr<api::WifiDirectSocket> Accept() override;
Exception Close() override;
private:
TCPServerSocket server_socket_;
std::unique_ptr<networkmanager::ActiveConnection> active_conn_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,40 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_DIRECT_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_DIRECT_SOCKET_H_
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/stream.h"
#include "internal/platform/implementation/linux/tcp_server_socket.h"
#include "internal/platform/implementation/wifi_direct.h"
namespace nearby {
namespace linux {
class WifiDirectSocket : public api::WifiDirectSocket {
public:
explicit WifiDirectSocket(TCPSocket socket) : socket_(std::move(socket)) {}
InputStream &GetInputStream() override { return socket_.GetInputStream(); }
OutputStream &GetOutputStream() override { return socket_.GetOutputStream(); }
Exception Close() override { return socket_.Close(); };
private:
TCPSocket socket_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,310 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cstring>
#include <memory>
#include <random>
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/utils.h"
#include "internal/platform/implementation/linux/wifi_hotspot.h"
#include "internal/platform/implementation/linux/wifi_hotspot_server_socket.h"
#include "internal/platform/implementation/linux/wifi_hotspot_socket.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
std::unique_ptr<api::WifiHotspotSocket>
NetworkManagerWifiHotspotMedium::ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) {
if (!ConnectedToWifi()) {
LOG(ERROR)
<< __func__
<< ": Cannot connect to service without an active WiFi hotspot";
return nullptr;
}
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOG(ERROR) << __func__
<< ": Error opening socket: " << std::strerror(errno);
return nullptr;
}
LOG(INFO) << __func__ << ": Connecting to " << ip_address << ":"
<< port;
struct sockaddr_in addr {};
addr.sin_addr.s_addr = inet_addr(std::string(ip_address).c_str());
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
auto ret =
connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr));
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error connecting to socket: "
<< std::strerror(errno);
return nullptr;
}
return std::make_unique<WifiHotspotSocket>(sock);
}
std::unique_ptr<api::WifiHotspotServerSocket>
NetworkManagerWifiHotspotMedium::ListenForService(int port) {
if (!WifiHotspotActive()) {
LOG(ERROR)
<< __func__
<< ": Cannot connect to service without an active WiFi hotspot";
return nullptr;
}
auto active_connection = wireless_device_->GetActiveConnection();
if (active_connection == nullptr) {
return nullptr;
}
auto ip4addresses = active_connection->GetIP4Addresses();
if (ip4addresses.empty()) {
LOG(ERROR)
<< __func__
<< "Could not find any IPv4 addresses for active connection "
<< active_connection->getObjectPath();
return nullptr;
}
auto sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOG(ERROR) << __func__
<< ": Error opening socket: " << std::strerror(errno);
return nullptr;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip4addresses[0].c_str());
addr.sin_port = htons(port);
auto ret =
bind(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr));
if (ret < 0) {
LOG(ERROR) << __func__
<< ": Error binding to socket: " << std::strerror(errno);
return nullptr;
}
LOG(INFO) << __func__ << ": Listening for services on "
<< ip4addresses[0] << ":" << port << " on device "
<< wireless_device_->getObjectPath();
ret = listen(sock, 0);
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error listening on socket: "
<< std::strerror(errno);
return nullptr;
}
return std::make_unique<NetworkManagerWifiHotspotServerSocket>(
sock, std::move(active_connection), network_manager_);
}
bool NetworkManagerWifiHotspotMedium::StartWifiHotspot(
HotspotCredentials *hotspot_credentials) {
if (WifiHotspotActive()) {
LOG(ERROR) << __func__ << ": " << wireless_device_->getObjectPath()
<< ": cannot start WiFi hotspot, a hotspot is already "
"active on this device";
return false;
}
std::string ssid = RandSSID();
hotspot_credentials->SetSSID(ssid);
std::string password = RandWPAPassphrase();
hotspot_credentials->SetPassword(password);
auto connection_id = NewUuidStr();
if (!connection_id.has_value()) {
LOG(ERROR) << __func__ << ": could not generate a connection UUID";
return false;
}
std::map<std::string, std::map<std::string, sdbus::Variant>>
connection_settings{
{
"connection",
{{"uuid", *connection_id},
{"id", "Google Nearby Hotspot"},
{"type", "802-11-wireless"},
{"zone", "Public"}},
},
{"802-11-wireless",
{{"assigned-mac-address", "random"},
{"ap-isolation", networkmanager::constants::kNMTernaryFalse},
{"mode", "ap"},
{"ssid", std::vector<uint8_t>(ssid.begin(), ssid.end())},
{"security", "802-11-wireless-security"}}},
{"802-11-wireless-security",
{{"pmf",
networkmanager::constants::setting::kWirelessSecurityPMFDisable},
{"key-mgmt", "wpa-psk"},
{"psk", password}}},
{"ipv4", {{"method", "shared"}}},
{"ipv6",
{
{"addr-gen-mode", networkmanager::constants::setting::
kIP6ConfigAddrGenModeStablePrivacy},
{"method", "shared"},
}}};
std::unique_ptr<networkmanager::ActiveConnection> active_conn;
try {
auto [path, active_path, result] =
network_manager_->AddAndActivateConnection2(
connection_settings, wireless_device_->getObjectPath(), "/",
{{"persist", "volatile"}, {"bind-activation", "dbus-client"}});
active_conn = std::make_unique<networkmanager::ActiveConnection>(
system_bus_, active_path);
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "AddAndActivateConnection2",
e);
return false;
}
auto [reason, timeout] = active_conn->WaitForConnection();
if (timeout) {
LOG(ERROR)
<< __func__ << ": "
<< ": timed out while waiting for connection "
<< active_conn->getObjectPath()
<< " to be activated, last NMActiveConnectionStateReason: "
<< reason->ToString();
DisconnectWifiHotspot();
return false;
}
LOG(INFO) << __func__ << ": Started a WiFi hotspot on device "
<< wireless_device_->getObjectPath() << " at "
<< active_conn->getObjectPath();
return true;
}
bool NetworkManagerWifiHotspotMedium::StopWifiHotspot() {
if (!WifiHotspotActive()) {
LOG(ERROR)
<< __func__ << ": " << wireless_device_->getObjectPath()
<< ": Cannot stop WiFi hotspot as a WiFi hotspot is not active";
}
// Get the active connection object for the hotspot AP.
sdbus::ObjectPath active_ap_path;
try {
active_ap_path = wireless_device_->ActiveAccessPoint();
if (active_ap_path.empty()) {
LOG(ERROR) << __func__ << ": No active access points on "
<< wireless_device_->getObjectPath();
return false;
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "ActiveAccessPoint", e);
}
auto object_manager = networkmanager::ObjectManager(system_bus_);
auto active_connection = wireless_device_->GetActiveConnection();
if (active_connection == nullptr) {
LOG(ERROR)
<< __func__
<< ": Could not find an active connection using the access point "
<< active_ap_path;
return false;
}
LOG(INFO) << __func__ << ": " << wireless_device_->getObjectPath()
<< ": Deactivating active connection "
<< active_connection->getObjectPath();
try {
network_manager_->DeactivateConnection(active_connection->getObjectPath());
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactivateConnection", e);
return false;
}
return true;
}
bool NetworkManagerWifiHotspotMedium::ConnectWifiHotspot(
HotspotCredentials *hotspot_credentials) {
if (hotspot_credentials == nullptr) {
LOG(ERROR) << __func__ << ": hotspot_credentials cannot be null";
return false;
}
auto ssid = hotspot_credentials->GetSSID();
auto password = hotspot_credentials->GetPassword();
return wireless_device_->ConnectToNetwork(ssid, password,
api::WifiAuthType::kWpaPsk) ==
api::WifiConnectionStatus::kConnected;
}
bool NetworkManagerWifiHotspotMedium::DisconnectWifiHotspot() {
if (!ConnectedToWifi()) {
LOG(ERROR) << __func__ << ": Not connected to a WiFi hotspot";
return false;
}
auto active_connection = wireless_device_->GetActiveConnection();
if (active_connection == nullptr) {
return false;
}
try {
network_manager_->DeactivateConnection(active_connection->getObjectPath());
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "DeactivateConnection", e);
return false;
}
return true;
}
bool NetworkManagerWifiHotspotMedium::WifiHotspotActive() {
try {
auto mode = wireless_device_->Mode();
return mode == networkmanager::constants::kNM80211ModeAP;
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
return false;
}
}
bool NetworkManagerWifiHotspotMedium::ConnectedToWifi() {
try {
auto mode = wireless_device_->Mode();
return mode == networkmanager::constants::kNM80211ModeInfra;
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(wireless_device_, "Mode", e);
return false;
}
}
} // namespace linux
} // namespace nearby
@@ -1,71 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_H_
#define PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_H_
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi_hotspot.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiHotspotMedium : public api::WifiHotspotMedium {
public:
NetworkManagerWifiHotspotMedium(
std::shared_ptr<networkmanager::NetworkManager> network_manager,
sdbus::ObjectPath wireless_device_object_path)
: system_bus_(network_manager->GetConnection()),
wireless_device_(std::make_unique<NetworkManagerWifiMedium>(
network_manager, std::move(wireless_device_object_path))),
network_manager_(std::move(network_manager)) {}
NetworkManagerWifiHotspotMedium(
std::shared_ptr<networkmanager::NetworkManager> network_manager,
std::unique_ptr<NetworkManagerWifiMedium> wireless_device)
: system_bus_(network_manager->GetConnection()),
wireless_device_(std::move(wireless_device)),
network_manager_(std::move(network_manager)) {}
bool IsInterfaceValid() const override { return true; }
std::unique_ptr<api::WifiHotspotSocket> ConnectToService(
absl::string_view ip_address, int port,
CancellationFlag *cancellation_flag) override;
std::unique_ptr<api::WifiHotspotServerSocket> ListenForService(
int port) override;
bool StartWifiHotspot(HotspotCredentials *hotspot_credentials) override;
bool StopWifiHotspot() override;
bool ConnectWifiHotspot(HotspotCredentials *hotspot_credentials) override;
bool DisconnectWifiHotspot() override;
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange()
override {
return absl::nullopt;
}
private:
bool WifiHotspotActive();
bool ConnectedToWifi();
std::shared_ptr<sdbus::IConnection> system_bus_;
std::unique_ptr<NetworkManagerWifiMedium> wireless_device_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,80 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <netinet/in.h>
#include <sys/socket.h>
#include "internal/platform/implementation/linux/wifi_hotspot_server_socket.h"
#include "internal/platform/implementation/linux/wifi_hotspot_socket.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
namespace nearby {
namespace linux {
std::string NetworkManagerWifiHotspotServerSocket::GetIPAddress() const {
auto ip4addresses = active_conn_->GetIP4Addresses();
if (ip4addresses.empty()) {
LOG(ERROR)
<< __func__
<< ": Could not find any IPv4 addresses for active connection "
<< active_conn_->getObjectPath();
return {};
}
return ip4addresses[0];
}
int NetworkManagerWifiHotspotServerSocket::GetPort() const {
struct sockaddr_in sin {};
socklen_t len = sizeof(sin);
auto ret =
getsockname(fd_.get(), reinterpret_cast<struct sockaddr *>(&sin), &len);
if (ret < 0) {
LOG(ERROR) << __func__ << ": Error getting information for socket "
<< fd_.get() << ": " << std::strerror(errno);
return 0;
}
return ntohs(sin.sin_port);
}
std::unique_ptr<api::WifiHotspotSocket>
NetworkManagerWifiHotspotServerSocket::Accept() {
struct sockaddr_in addr {};
socklen_t len = sizeof(addr);
auto conn =
accept(fd_.get(), reinterpret_cast<struct sockaddr *>(&addr), &len);
if (conn < 0) {
LOG(ERROR) << __func__
<< ": Error accepting incoming connections on socket "
<< fd_.get() << ": " << std::strerror(errno);
return nullptr;
}
return std::make_unique<WifiHotspotSocket>(conn);
}
Exception NetworkManagerWifiHotspotServerSocket::Close() {
int fd = fd_.release();
shutdown(fd, SHUT_RDWR);
auto ret = close(fd_.release());
if (ret < 0) {
LOG(ERROR) << __func__
<< ": Error closing socket: " << std::strerror(errno);
return {Exception::kFailed};
}
return {Exception::kSuccess};
}
} // namespace linux
} // namespace nearby
@@ -1,49 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_SERVER_SOCKET_H_
#include <sdbus-c++/IConnection.h>
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/wifi_hotspot.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiHotspotServerSocket
: public api::WifiHotspotServerSocket {
public:
NetworkManagerWifiHotspotServerSocket(
int socket, std::unique_ptr<networkmanager::ActiveConnection> active_conn,
std::shared_ptr<networkmanager::NetworkManager> network_manager)
: fd_(socket),
active_conn_(std::move(active_conn)),
network_manager_(std::move(network_manager)) {}
std::string GetIPAddress() const override;
int GetPort() const override;
std::unique_ptr<api::WifiHotspotSocket> Accept() override;
Exception Close() override;
private:
sdbus::UnixFd fd_;
std::unique_ptr<networkmanager::ActiveConnection> active_conn_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,47 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_HOTSPOT_SOCKET_H_
#include "internal/platform/implementation/linux/stream.h"
#include "internal/platform/implementation/wifi_hotspot.h"
namespace nearby {
namespace linux {
class WifiHotspotSocket : public api::WifiHotspotSocket {
public:
explicit WifiHotspotSocket(int connection_fd)
: fd_(sdbus::UnixFd(connection_fd)),
output_stream_(fd_),
input_stream_(fd_) {}
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
@@ -1,227 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cerrno>
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Types.h>
#include "absl/strings/substitute.h"
#include "internal/platform/implementation/linux/avahi.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/tcp_server_socket.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(
std::shared_ptr<networkmanager::NetworkManager> network_manager)
: system_bus_(network_manager->GetConnection()),
network_manager_(std::move(network_manager)),
avahi_(std::make_shared<avahi::Server>(*system_bus_)) {}
bool WifiLanMedium::IsNetworkConnected() const {
auto state = network_manager_->getState();
return state == networkmanager::NetworkManager::kNMStateConnectedLocal ||
state == networkmanager::NetworkManager::kNMStateConnectedSite ||
state == networkmanager::NetworkManager::kNMStateConnectedGlobal;
}
std::optional<std::pair<std::string, std::string>> entry_group_key(
const NsdServiceInfo &nsd_service_info) {
auto name = nsd_service_info.GetServiceName();
if (name.empty()) {
LOG(ERROR) << __func__ << ": service name cannot be empty";
return std::nullopt;
}
auto type = nsd_service_info.GetServiceType();
if (type.empty()) {
LOG(ERROR) << __func__ << ": service type cannot be empty";
return std::nullopt;
}
return std::make_pair(std::move(name), std::move(type));
}
bool WifiLanMedium::StartAdvertising(const NsdServiceInfo &nsd_service_info) {
auto key = entry_group_key(nsd_service_info);
if (!key.has_value()) {
return false;
}
{
absl::ReaderMutexLock l(&entry_groups_mutex_);
if (entry_groups_.count(*key) == 1) {
LOG(ERROR) << __func__
<< ": advertising is already active for this service";
return false;
}
}
auto txt_records_map = nsd_service_info.GetTxtRecords();
std::vector<std::vector<std::uint8_t>> 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<std::uint8_t>(entry.begin(), entry.end());
}
sdbus::ObjectPath entry_group_path;
try {
entry_group_path = avahi_->EntryGroupNew();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(avahi_, "EntryGroupNew", e);
return false;
}
auto entry_group =
std::make_unique<avahi::EntryGroup>(*system_bus_, entry_group_path);
try {
entry_group->AddService(
-1, // AVAHI_IF_UNSPEC
-1, // AVAHI_PROTO_UNSPED
0, nsd_service_info.GetServiceName(), nsd_service_info.GetServiceType(),
std::string(), std::string(), nsd_service_info.GetPort(), txt_records);
entry_group->Commit();
} catch (const sdbus::Error &e) {
LOG(ERROR) << __func__ << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while adding service";
return false;
}
absl::MutexLock l(&entry_groups_mutex_);
entry_groups_.insert({*key, std::move(entry_group)});
return true;
}
bool WifiLanMedium::StopAdvertising(const NsdServiceInfo &nsd_service_info) {
auto key = entry_group_key(nsd_service_info);
if (!key.has_value()) {
return false;
}
absl::MutexLock l(&entry_groups_mutex_);
if (entry_groups_.count(*key) == 0) {
LOG(ERROR) << __func__
<< ": Advertising is already inactive for this service.";
return false;
}
entry_groups_.erase(*key);
return true;
}
bool WifiLanMedium::StartDiscovery(
const std::string &service_type,
api::WifiLanMedium::DiscoveredServiceCallback callback) {
{
absl::ReaderMutexLock l(&service_browsers_mutex_);
if (service_browsers_.count(service_type) != 0) {
auto &object = service_browsers_[service_type];
LOG(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);
LOG(INFO)
<< __func__
<< ": Created a new org.freedesktop.Avahi.ServiceBrowser object at "
<< browser_object_path;
absl::MutexLock l(&service_browsers_mutex_);
service_browsers_.emplace(
service_type,
std::make_unique<avahi::ServiceBrowser>(
*system_bus_, browser_object_path, std::move(callback), avahi_));
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(avahi_, "ServiceBrowserPrepare", e);
return false;
}
service_browsers_mutex_.ReaderLock();
auto &browser = service_browsers_[service_type];
service_browsers_mutex_.ReaderUnlock();
try {
LOG(INFO) << __func__ << ": Starting service discovery for "
<< browser->getObjectPath();
browser->Start();
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(browser, "Start", e);
return false;
}
return true;
}
bool WifiLanMedium::StopDiscovery(const std::string &service_type) {
absl::MutexLock l(&service_browsers_mutex_);
if (service_browsers_.count(service_type) == 0) {
LOG(ERROR) << __func__ << ": Service type " << service_type
<< " has not been registered for discovery";
return false;
}
service_browsers_.erase(service_type);
return true;
}
std::unique_ptr<api::WifiLanSocket> WifiLanMedium::ConnectToService(
const std::string &ip_address, int port,
CancellationFlag *cancellation_flag) {
auto socket = TCPSocket::Connect(ip_address, port);
if (!socket.has_value()) return nullptr;
return std::make_unique<WifiLanSocket>(*socket);
}
std::unique_ptr<api::WifiLanServerSocket> WifiLanMedium::ListenForService(
int port) {
auto socket = TCPServerSocket::Listen(std::nullopt, port);
if (!socket.has_value()) return nullptr;
return std::make_unique<WifiLanServerSocket>(std::move(*socket),
network_manager_);
}
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange() {
return absl::nullopt;
}
} // namespace linux
} // namespace nearby
@@ -1,80 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_H_
#define PLATFORM_IMPL_LINUX_WIFI_LAN_H_
#include <sdbus-c++/IConnection.h>
#include <memory>
#include "absl/container/flat_hash_map.h"
#include "absl/synchronization/mutex.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:
explicit WifiLanMedium(std::shared_ptr<networkmanager::NetworkManager> network_manager);
bool IsNetworkConnected() const override;
bool StartAdvertising(const NsdServiceInfo &nsd_service_info) override
ABSL_LOCKS_EXCLUDED(entry_groups_mutex_);
bool StopAdvertising(const NsdServiceInfo &nsd_service_info) override
ABSL_LOCKS_EXCLUDED(entry_groups_mutex_);
bool StartDiscovery(const std::string &service_type,
DiscoveredServiceCallback callback) override
ABSL_LOCKS_EXCLUDED(service_browsers_mutex_);
bool StopDiscovery(const std::string &service_type) override
ABSL_LOCKS_EXCLUDED(service_browsers_mutex_);
std::unique_ptr<api::WifiLanSocket> 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<api::WifiLanSocket> ConnectToService(
const std::string &ip_address, int port,
CancellationFlag *cancellation_flag) override;
std::unique_ptr<api::WifiLanServerSocket> ListenForService(
int port = 0) override;
absl::optional<std::pair<std::int32_t, std::int32_t>> GetDynamicPortRange()
override {
return std::nullopt;
}
private:
std::shared_ptr<sdbus::IConnection> system_bus_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
std::shared_ptr<avahi::Server> avahi_;
absl::Mutex entry_groups_mutex_;
absl::flat_hash_map<std::pair<std::string, std::string>,
std::unique_ptr<avahi::EntryGroup>>
entry_groups_ ABSL_GUARDED_BY(entry_groups_mutex_);
absl::Mutex service_browsers_mutex_;
absl::flat_hash_map<std::string, std::unique_ptr<avahi::ServiceBrowser>>
service_browsers_ ABSL_GUARDED_BY(service_browsers_mutex_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,91 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <memory>
#include <sdbus-c++/Types.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/wifi_lan_server_socket.h"
#include "internal/platform/implementation/linux/wifi_lan_socket.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace linux {
std::string WifiLanServerSocket::GetIPAddress() const {
std::vector<sdbus::ObjectPath> connection_paths;
try {
connection_paths = network_manager_->ActiveConnections();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(network_manager_, "ActiveConnections", e);
return std::string();
}
for (auto &path : connection_paths) {
auto active_connection =
std::make_unique<networkmanager::ActiveConnection>(system_bus_, path);
std::string conn_type;
try {
conn_type = active_connection->Type();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(active_connection, "Type", e);
continue;
}
if (conn_type == "802-11-wireless" || conn_type == "802-3-ethernet") {
auto ip4config_path = active_connection->Ip4Config();
networkmanager::IP4Config ip4config(system_bus_, ip4config_path);
std::vector<std::map<std::string, sdbus::Variant>> address_data;
try {
address_data = ip4config.AddressData();
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&ip4config, "IP4Config", e);
continue;
}
if (address_data.size() > 0) {
return address_data[0]["address"];
}
}
}
LOG(ERROR)
<< __func__ << ": Could not find any active IP addresses for this device";
return std::string();
}
int WifiLanServerSocket::GetPort() const {
return server_socket_.GetPort();
}
std::unique_ptr<api::WifiLanSocket> WifiLanServerSocket::Accept() {
auto sock = server_socket_.Accept();
if (!sock.has_value()) return nullptr;
return std::make_unique<WifiLanSocket>(std::move(*sock));
}
Exception WifiLanServerSocket::Close() {
return server_socket_.Close();
}
} // namespace linux
} // namespace nearby
@@ -1,52 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_SERVER_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_LAN_SERVER_SOCKET_H_
#include <netinet/in.h>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Types.h>
#include "internal/platform/exception.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/tcp_server_socket.h"
#include "internal/platform/implementation/wifi_lan.h"
namespace nearby {
namespace linux {
class WifiLanServerSocket : public api::WifiLanServerSocket {
public:
explicit WifiLanServerSocket(
TCPServerSocket socket,
std::shared_ptr<networkmanager::NetworkManager> network_manager)
: server_socket_(std::move(socket)),
network_manager_(std::move(network_manager)),
system_bus_(network_manager_->GetConnection()) {}
std::string GetIPAddress() const override;
int GetPort() const override;
std::unique_ptr<api::WifiLanSocket> Accept() override;
Exception Close() override;
private:
TCPServerSocket server_socket_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
std::shared_ptr<sdbus::IConnection> system_bus_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,48 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_
#define PLATFORM_IMPL_LINUX_WIFI_LAN_SOCKET_H_
#include <optional>
#include <sdbus-c++/Types.h>
#include "internal/platform/implementation/linux/stream.h"
#include "internal/platform/implementation/linux/tcp_server_socket.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:
explicit WifiLanSocket(TCPSocket sock) : socket_(std::move(sock)) {}
nearby::InputStream &GetInputStream() override {
return socket_.GetInputStream();
}
nearby::OutputStream &GetOutputStream() override {
return socket_.GetOutputStream();
}
Exception Close() override { return socket_.Close(); }
private:
TCPSocket socket_;
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,355 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <climits>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include <systemd/sd-id128.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/dbus.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/device_wireless_client.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/linux/utils.h"
#include "internal/platform/implementation/linux/wifi_medium.h"
#include "internal/platform/implementation/wifi.h"
namespace nearby {
namespace linux {
api::WifiCapability &NetworkManagerWifiMedium::GetCapability() {
try {
auto cap_mask = WirelessCapabilities();
// https://networkmanager.dev/docs/api/latest/nm-dbus-types.html#NMDeviceWifiCapabilities
capability_.supports_5_ghz = (cap_mask & 0x00000400) != 0;
capability_.supports_6_ghz = false;
capability_.support_wifi_direct = true;
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(&getProxy(), "WirelessCapabilities", e);
}
return capability_;
}
inline std::int32_t to_signed(std::uint32_t v) {
if (v <= INT_MAX) return static_cast<std::int32_t>(v);
if (v >= INT_MIN) return static_cast<std::int32_t>(v - INT_MIN) + INT_MIN;
return INT_MAX;
}
api::WifiInformation &NetworkManagerWifiMedium::GetInformation() {
std::unique_ptr<NetworkManagerAccessPoint> active_access_point;
try {
auto ap_path = ActiveAccessPoint();
if (ap_path.empty()) {
information_ = api::WifiInformation{false};
return information_;
}
active_access_point =
std::make_unique<NetworkManagerAccessPoint>(*system_bus_, ap_path);
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "ActiveAccessPoint", e);
}
try {
auto ssid_vec = active_access_point->Ssid();
std::string ssid{ssid_vec.begin(), ssid_vec.end()};
information_ =
api::WifiInformation{true, ssid, active_access_point->HwAddress(),
to_signed(active_access_point->Frequency())};
networkmanager::ObjectManager manager(system_bus_);
auto ip4config = manager.GetIp4Config(active_access_point->getObjectPath());
if (ip4config != nullptr) {
auto address_data = ip4config->AddressData();
if (!address_data.empty()) {
std::string address = address_data[0]["address"];
information_.ip_address_dot_decimal = address;
struct in_addr addr {};
inet_aton(address.c_str(), &addr);
char addr_bytes[4];
memcpy(addr_bytes, &addr.s_addr, sizeof(addr_bytes));
information_.ip_address_4_bytes = std::string(addr_bytes, 4);
}
} else {
LOG(ERROR) << __func__ << ": " << getObjectPath()
<< ": Could not find the Ip4Config object for "
<< active_access_point->getObjectPath();
}
} catch (const sdbus::Error &e) {
LOG(ERROR)
<< __func__ << ": " << getObjectPath() << ": Got error '" << e.getName()
<< "' with message '" << e.getMessage()
<< "' while populating network information for access point "
<< active_access_point->getObjectPath();
}
return information_;
}
void NetworkManagerWifiMedium::onPropertiesChanged(
const std::string &interfaceName,
const std::map<std::string, sdbus::Variant> &changedProperties,
const std::vector<std::string> &invalidatedProperties) {
if (interfaceName != org::freedesktop::NetworkManager::Device::
Wireless_proxy::INTERFACE_NAME) {
return;
}
if (changedProperties.count("LastScan") == 1) {
absl::MutexLock l(&last_scan_lock_);
last_scan_ = changedProperties.at("LastScan");
}
}
bool NetworkManagerWifiMedium::Scan(
const api::WifiMedium::ScanResultCallback &scan_result_callback) {
// absl::MutexLock l(&scan_result_callback_lock_);
// scan_result_callback_ = scan_result_callback;
try {
RequestScan({});
} catch (const sdbus::Error &e) {
scan_result_callback_ = std::nullopt;
DBUS_LOG_METHOD_CALL_ERROR(&getProxy(), "RequestScan", e);
return false;
}
return false;
}
std::shared_ptr<NetworkManagerAccessPoint>
NetworkManagerWifiMedium::SearchBySSIDNoScan(
std::vector<std::uint8_t> &ssid_bytes) {
absl::ReaderMutexLock l(&known_access_points_lock_);
for (auto &[object_path, ap] : known_access_points_) {
try {
if (ap->Ssid() == ssid_bytes) {
return ap;
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(ap, "Ssid", e);
}
}
return nullptr;
}
std::shared_ptr<NetworkManagerAccessPoint>
NetworkManagerWifiMedium::SearchBySSID(absl::string_view ssid,
absl::Duration scan_timeout) {
std::vector<std::uint8_t> ssid_bytes(ssid.begin(), ssid.end());
// First, try to see if we already know an AP with this SSID.
auto ap = SearchBySSIDNoScan(ssid_bytes);
if (ap != nullptr) {
return ap;
}
LOG(INFO) << __func__ << ": " << getObjectPath() << ": SSID " << ssid
<< " not currently known by device " << getObjectPath()
<< ", requesting a scan";
std::int64_t cur_last_scan;
{
absl::ReaderMutexLock l(&last_scan_lock_);
cur_last_scan = last_scan_;
}
// Otherwise, request a Scan first and wait for it to finish.
try {
RequestScan(
{{"ssids", std::vector<std::vector<std::uint8_t>>{ssid_bytes}}});
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "RequestScan", e);
}
auto scan_finish = [&, cur_last_scan]() {
last_scan_lock_.AssertReaderHeld();
return cur_last_scan != last_scan_;
};
absl::Condition cond(&scan_finish);
bool success = last_scan_lock_.ReaderLockWhenWithTimeout(cond, scan_timeout);
last_scan_lock_.ReaderUnlock();
if (!success) {
LOG(WARNING) << __func__ << ": " << getObjectPath()
<< ": timed out waiting for scan to finish";
}
ap = SearchBySSIDNoScan(ssid_bytes);
if (ap == nullptr) {
LOG(WARNING) << __func__ << ": " << getObjectPath()
<< ": Couldn't find SSID " << ssid;
}
return ap;
}
static inline std::pair<std::optional<std::string>, std::string>
AuthAlgAndKeyMgmt(api::WifiAuthType auth_type) {
switch (auth_type) {
case api::WifiAuthType::kUnknown:
case api::WifiAuthType::kOpen:
return {"open", "none"};
case api::WifiAuthType::kWpaPsk:
return {std::nullopt, "wpa-psk"};
case api::WifiAuthType::kWep:
return {"none", "wep"};
}
}
api::WifiConnectionStatus NetworkManagerWifiMedium::ConnectToNetwork(
absl::string_view ssid, absl::string_view password,
api::WifiAuthType auth_type) {
auto ap = SearchBySSID(ssid);
if (ap == nullptr) {
LOG(ERROR) << __func__ << ": " << getObjectPath()
<< ": Couldn't find SSID " << ssid;
return api::WifiConnectionStatus::kConnectionFailure;
}
auto connection_id = NewUuidStr();
if (!connection_id.has_value()) {
LOG(ERROR) << __func__ << ": could not generate a connection UUID";
return api::WifiConnectionStatus::kUnknown;
}
auto [auth_alg, key_mgmt] = AuthAlgAndKeyMgmt(auth_type);
std::map<std::string, std::map<std::string, sdbus::Variant>>
connection_settings{
{"connection",
{
{"uuid", *connection_id},
{"autoconnect", true},
{"id", std::string(ssid)},
{"type", "802-11-wireless"},
{"zone", "Public"},
}},
{"802-11-wireless",
{
{"ssid", std::vector<uint8_t>(ssid.begin(), ssid.end())},
{"mode", "infrastructure"},
{"security", "802-11-wireless-security"},
{"assigned-mac-address", "random"},
}},
{"802-11-wireless-security", {{"key-mgmt", key_mgmt}}}};
if (!password.empty()) {
connection_settings["802-11-wireless-security"]["psk"] =
std::string(password);
}
if (auth_alg.has_value()) {
connection_settings["802-11-wireless-security"]["auth-alg"] = *auth_alg;
}
sdbus::ObjectPath connection_path, active_conn_path;
try {
auto [cp, acp, _r] = network_manager_->AddAndActivateConnection2(
connection_settings, getObjectPath(), ap->getObjectPath(),
{{"persist", "volatile"}, {"bind-activation", "dbus-client"}});
connection_path = std::move(cp);
active_conn_path = std::move(acp);
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(this, "AddAndActivateConnection2", e);
return api::WifiConnectionStatus::kUnknown;
}
LOG(INFO) << __func__ << ": " << getObjectPath()
<< ": Added a new connection at " << connection_path;
auto active_connection =
networkmanager::ActiveConnection(system_bus_, active_conn_path);
auto [reason, timeout] = active_connection.WaitForConnection();
if (timeout) {
LOG(ERROR)
<< __func__ << ": " << getObjectPath()
<< ": timed out while waiting for connection " << active_conn_path
<< " to be activated, last NMActiveConnectionStateReason: "
<< reason->ToString();
return api::WifiConnectionStatus::kUnknown;
}
if (reason.has_value()) {
LOG(ERROR) << __func__ << ": " << getObjectPath() << ": connection "
<< active_conn_path
<< " failed to activate, NMActiveConnectionStateReason:"
<< reason->ToString();
if (reason->value ==
networkmanager::ActiveConnection::ActiveConnectionStateReason::
kStateReasonNoSecrets ||
reason->value ==
networkmanager::ActiveConnection::ActiveConnectionStateReason::
kStateReasonLoginFailed)
return api::WifiConnectionStatus::kAuthFailure;
}
LOG(INFO) << __func__ << ": Activated connection " << connection_path;
return api::WifiConnectionStatus::kConnected;
}
bool NetworkManagerWifiMedium::VerifyInternetConnectivity() {
try {
std::uint32_t connectivity = network_manager_->CheckConnectivity();
return connectivity == 4; // NM_CONNECTIVITY_FULL
} catch (const sdbus::Error &e) {
DBUS_LOG_METHOD_CALL_ERROR(network_manager_, "CheckConnectivity", e);
return false;
}
}
std::string NetworkManagerWifiMedium::GetIpAddress() {
GetInformation();
return information_.ip_address_dot_decimal;
}
std::unique_ptr<networkmanager::ActiveConnection>
NetworkManagerWifiMedium::GetActiveConnection() {
sdbus::ObjectPath active_ap_path;
try {
active_ap_path = ActiveAccessPoint();
if (active_ap_path.empty()) {
LOG(ERROR) << __func__ << ": No active access points on "
<< getObjectPath();
return nullptr;
}
} catch (const sdbus::Error &e) {
DBUS_LOG_PROPERTY_GET_ERROR(this, "ActiveAccessPoint", e);
return nullptr;
}
auto object_manager = networkmanager::ObjectManager(system_bus_);
auto conn = object_manager.GetActiveConnectionForAccessPoint(active_ap_path,
getObjectPath());
if (conn == nullptr) {
LOG(ERROR)
<< __func__
<< ": Could not find an active connection using the access point "
<< active_ap_path << " and device " << getObjectPath();
}
return conn;
}
} // namespace linux
} // namespace nearby
@@ -1,139 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PLATFORM_IMPL_LINUX_WIFI_MEDIUM_H_
#define PLATFORM_IMPL_LINUX_WIFI_MEDIUM_H_
#include <atomic>
#include <functional>
#include <list>
#include <memory>
#include <optional>
#include <ostream>
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Types.h>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/linux/generated/dbus/networkmanager/device_wireless_client.h"
#include "internal/platform/implementation/linux/network_manager.h"
#include "internal/platform/implementation/linux/network_manager_access_point.h"
#include "internal/platform/implementation/linux/network_manager_active_connection.h"
#include "internal/platform/implementation/wifi.h"
namespace nearby {
namespace linux {
class NetworkManagerWifiMedium
: public api::WifiMedium,
public sdbus::ProxyInterfaces<
org::freedesktop::NetworkManager::Device::Wireless_proxy,
sdbus::Properties_proxy> {
public:
NetworkManagerWifiMedium(const NetworkManagerWifiMedium &) = delete;
NetworkManagerWifiMedium(NetworkManagerWifiMedium &&) = delete;
NetworkManagerWifiMedium &operator=(const NetworkManagerWifiMedium &) =
delete;
NetworkManagerWifiMedium &operator=(NetworkManagerWifiMedium &&) = delete;
NetworkManagerWifiMedium(
std::shared_ptr<networkmanager::NetworkManager> network_manager,
const sdbus::ObjectPath &wireless_device_object_path)
: ProxyInterfaces(*network_manager->GetConnection(),
"org.freedesktop.NetworkManager",
wireless_device_object_path),
system_bus_(network_manager->GetConnection()),
network_manager_(std::move(network_manager)),
last_scan_(-1) {
registerProxy();
}
~NetworkManagerWifiMedium() override { unregisterProxy(); }
class ScanResultCallback : public api::WifiMedium::ScanResultCallback {
public:
void OnScanResults(
const std::vector<api::WifiScanResult> &scan_results) override {
// TODO: Add implementation at some point
}
};
bool IsInterfaceValid() const override { return true; };
api::WifiCapability &GetCapability() override;
api::WifiInformation &GetInformation() override;
bool Scan(
const api::WifiMedium::ScanResultCallback &scan_result_callback) override;
std::shared_ptr<NetworkManagerAccessPoint> SearchBySSID(
absl::string_view ssid, absl::Duration scan_timeout = absl::Seconds(15))
ABSL_LOCKS_EXCLUDED(known_access_points_lock_);
api::WifiConnectionStatus ConnectToNetwork(
absl::string_view ssid, absl::string_view password,
api::WifiAuthType auth_type) override;
bool VerifyInternetConnectivity() override;
std::string GetIpAddress() override;
std::unique_ptr<networkmanager::ActiveConnection> GetActiveConnection();
protected:
void onPropertiesChanged(
const std::string &interfaceName,
const std::map<std::string, sdbus::Variant> &changedProperties,
const std::vector<std::string> &invalidatedProperties) override;
void onAccessPointAdded(const sdbus::ObjectPath &access_point) override
ABSL_LOCKS_EXCLUDED(known_access_points_lock_) {
absl::MutexLock l(&known_access_points_lock_);
known_access_points_.erase(access_point);
known_access_points_.emplace(access_point,
std::make_shared<NetworkManagerAccessPoint>(
getProxy().getConnection(), access_point));
}
void onAccessPointRemoved(const sdbus::ObjectPath &access_point) override
ABSL_LOCKS_EXCLUDED(known_access_points_lock_) {
absl::MutexLock l(&known_access_points_lock_);
known_access_points_.erase(access_point);
}
private:
std::shared_ptr<NetworkManagerAccessPoint> SearchBySSIDNoScan(
std::vector<std::uint8_t> &ssid)
ABSL_LOCKS_EXCLUDED(known_access_points_lock_);
std::shared_ptr<sdbus::IConnection> system_bus_;
std::shared_ptr<networkmanager::NetworkManager> network_manager_;
api::WifiCapability capability_;
api::WifiInformation information_{false};
absl::Mutex known_access_points_lock_;
absl::flat_hash_map<sdbus::ObjectPath,
std::shared_ptr<NetworkManagerAccessPoint>>
known_access_points_ ABSL_GUARDED_BY(known_access_points_lock_);
absl::Mutex scan_result_callback_lock_;
std::optional<
std::reference_wrapper<const api::WifiMedium::ScanResultCallback>>
scan_result_callback_ ABSL_GUARDED_BY(scan_result_callback_lock_);
absl::Mutex last_scan_lock_;
std::int64_t last_scan_ ABSL_GUARDED_BY(last_scan_lock_);
};
} // namespace linux
} // namespace nearby
#endif
@@ -1,30 +0,0 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#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;
};
} // namespace api
} // namespace nearby
#endif