Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 125 additions & 46 deletions examples/connmanctl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ using Amarula::DBus::G::Connman::TechProperties;
using State = Amarula::DBus::G::Connman::ServProperties::State;
using TechnologyType = TechProperties::Type;

constexpr std::size_t MIN_WIFI_PASSPHRASE_LENGTH = 8;

std::atomic<bool> has_message{false};
std::ostringstream message;
std::mutex message_mutex;
Expand Down Expand Up @@ -65,7 +67,8 @@ enum class Command : std::uint8_t {
Disconnect,
Remove,
Agent,
Quit
Quit,
Tethering
};

inline const std::unordered_map<Command, std::string_view> command_map = {
Expand All @@ -78,7 +81,8 @@ inline const std::unordered_map<Command, std::string_view> command_map = {
{Command::Disconnect, "disconnect"},
{Command::Remove, "remove"},
{Command::Agent, "agent"},
{Command::Quit, "quit"}};
{Command::Quit, "quit"},
{Command::Tethering, "tether"}};

inline const std::unordered_map<TechnologyType, std::string_view> tech_map = {
{TechnologyType::Ethernet, "ethernet"},
Expand Down Expand Up @@ -170,7 +174,8 @@ auto completion(const char* text, int start, int end) -> char** {
completion_mode = Mode::OnOff;
} else if (command == command_map.at(Command::Enable) ||
command == command_map.at(Command::Disable) ||
command == command_map.at(Command::Scan)) {
command == command_map.at(Command::Scan) ||
command == command_map.at(Command::Tethering)) {
completion_mode = Mode::TechHash;
} else if (command == command_map.at(Command::Connect) ||
command == command_map.at(Command::Disconnect) ||
Expand Down Expand Up @@ -265,6 +270,10 @@ auto main() -> int {
std::string cmd;
std::string arg;
iss >> cmd >> arg;
auto match_technology = [&arg](const auto& technology) {
const auto props = technology->properties();
return tech_map.at(props.getType()) == arg;
};
auto match_service = [&arg](const auto& service) {
const auto props = service->properties();
const auto name = props.getName();
Expand Down Expand Up @@ -362,26 +371,24 @@ auto main() -> int {
}
}
const auto techs = manager->technologies();
for (const auto& tech : techs) {
const auto props = tech->properties();
auto iterator = std::ranges::find_if(techs, match_technology);
if (iterator != techs.end()) {
const auto props = (*iterator)->properties();
const auto name = props.getName();
if (tech_map.at(props.getType()) == arg) {
std::cout << "Scanning " << name << "...\n";
tech->scan([name](bool success) {
{
std::lock_guard<std::mutex> lock(message_mutex);
if (success) {
message << "Technology " << name
<< " scanned successfully.\n";
} else {
message << "Failed to scan technology " << name
<< ".\n";
}
std::cout << "Scanning " << name << "...\n";
(*iterator)->scan([name](bool success) {
{
std::lock_guard<std::mutex> lock(message_mutex);
if (success) {
message << "Technology " << name
<< " scanned successfully.\n";
} else {
message << "Failed to scan technology " << name
<< ".\n";
}
has_message = true;
});
break;
}
}
has_message = true;
});
}
} else if (cmd == command_map.at(Command::Enable) ||
cmd == command_map.at(Command::Disable)) {
Expand All @@ -403,39 +410,111 @@ auto main() -> int {
std::cout << (enable ? "Enabling" : "Disabling")
<< " technology: " << arg << "\n";
const auto techs = manager->technologies();
for (const auto& tech : techs) {
const auto props = tech->properties();
auto iterator = std::ranges::find_if(techs, match_technology);
if (iterator != techs.end()) {
const auto props = (*iterator)->properties();
const auto name = props.getName();
if (tech_map.at(props.getType()) == arg) {
if ((!props.isPowered() &&
cmd == enable_disable_container.at(0)) ||
(props.isPowered() &&
cmd == enable_disable_container.at(1))) {
std::cout << (enable ? "Enabling " : "Disabling ")
<< name << "...\n";
tech->setPowered(enable, [name, enable](bool success) {
{
std::lock_guard<std::mutex> lock(message_mutex);
if (success) {
message
<< "Technology " << name
if ((!props.isPowered() &&
cmd == enable_disable_container.at(0)) ||
(props.isPowered() &&
cmd == enable_disable_container.at(1))) {
std::cout << (enable ? "Enabling " : "Disabling ") << name
<< "...\n";
(*iterator)->setPowered(enable, [name,
enable](bool success) {
{
std::lock_guard<std::mutex> lock(message_mutex);
if (success) {
message << "Technology " << name
<< (enable ? " enabled" : " disabled")
<< " successfully.\n";
} else {
message << "Failed to "
<< (enable ? " enable" : " disable")
<< " technology " << name << "\n";
}
} else {
message << "Failed to "
<< (enable ? " enable" : " disable")
<< " technology " << name << "\n";
}
}

has_message = true;
});
has_message = true;
});

} else {
std::cout << "Technology " << name << " is already "
<< (enable ? "enabled" : "disabled") << "\n";
} else {
std::cout << "Technology " << name << " is already "
<< (enable ? "enabled" : "disabled") << "\n";
}
}

} else if (cmd == command_map.at(Command::Tethering)) {
std::string arg1;
std::string arg2;
iss >> arg1 >> arg2;
{
std::lock_guard<std::mutex> lock(hash_mutex);
if (arg.empty() ||
std::find(technologies_container.begin(),
technologies_container.end(),
arg) == technologies_container.end() ||
arg1.empty() ||
(arg1 != on_off_container[0] &&
arg1 != on_off_container[1]) ||
(arg == tech_map.at(TechnologyType::Wifi) &&
arg1 == on_off_container[0] && arg2.empty())) {
std::cout << "Usage: tether <technology> "
<< on_off_container[0] << "/"
<< on_off_container[1]
<< " <SSID> <PASSPHRASE> <FREQUENCY>\n";
std::cout << "Available technologies:";
printContainer(technologies_container);
continue;
}
}
const auto techs = manager->technologies();
auto iterator = std::ranges::find_if(techs, match_technology);
if (iterator != techs.end()) {
if (arg == tech_map.at(TechnologyType::Wifi)) {
std::string arg3;
std::string arg4;
iss >> arg3 >> arg4;
(*iterator)->setTetheringIdentifier(arg2);

if (!arg3.empty()) {
if (arg3.size() >= MIN_WIFI_PASSPHRASE_LENGTH) {
(*iterator)->setTetheringPassphrase(arg3);
} else {
std::cout << "Error setting wifi passphrase\n"
<< "Passphrase must be at least "
<< MIN_WIFI_PASSPHRASE_LENGTH
<< " characters long\n";
continue;
}
}

if (!arg4.empty() &&
std::all_of(arg4.begin(), arg4.end(), ::isdigit)) {
(*iterator)->setTetheringFreq(std::stoi(arg4));
Comment thread
EddyTheCo marked this conversation as resolved.
}
}

const auto enable = arg1 == on_off_container[0];
std::cout << (enable ? "Enabling" : "Disabling")
<< " tethering on " << arg << "\n";
(*iterator)->setTethering(enable, [arg, enable](bool success) {
{
std::lock_guard<std::mutex> lock(message_mutex);
if (success) {
message << "Tethering on technology " << arg
<< (enable ? " enabled" : " disabled")
<< " successfully.\n";
} else {
message << "Failed to"
<< (enable ? " enable" : " disable")
<< " tethering on "
"technology "
<< arg << "\n";
}
}
has_message = true;
});
}
} else if (cmd == command_map.at(Command::Connect) ||
cmd == command_map.at(Command::Disconnect)) {
Expand Down
17 changes: 16 additions & 1 deletion include/amarula/dbus/connman/gtechnology.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ struct TechProperties {
[[nodiscard]] auto isConnected() const { return connected_; }
[[nodiscard]] auto isTethering() const { return tethering_; }
[[nodiscard]] auto getTetheringFreq() const { return tethering_freq_; }
[[nodiscard]] auto getTetheringIdentifier() const {
return tethering_identifier_;
}
[[nodiscard]] auto getTetheringPassphrase() const {
return tethering_passphrase_;
}
friend auto operator<<(std::ostream& ostr,
const TechProperties& object) -> std::ostream&;

Expand All @@ -37,8 +43,10 @@ struct TechProperties {
bool connected_ = false;
bool tethering_ = false;
std::string name_;
std::string tethering_identifier_;
std::string tethering_passphrase_;
Type type_;
int tethering_freq_{0};
uint32_t tethering_freq_{0};

void update(const gchar* key, GVariant* value);

Expand All @@ -54,6 +62,13 @@ class Technology : public DBusProxy<TechProperties> {
public:
using Properties = TechProperties;
void setPowered(bool powered, PropertiesSetCallback callback = nullptr);
void setTethering(bool tethering, PropertiesSetCallback callback = nullptr);
void setTetheringIdentifier(const std::string& identifier,
PropertiesSetCallback callback = nullptr);
void setTetheringPassphrase(const std::string& passphrase,
PropertiesSetCallback callback = nullptr);
void setTetheringFreq(uint32_t frequency,
PropertiesSetCallback callback = nullptr);
void scan(PropertiesSetCallback callback = nullptr);

friend class Manager;
Expand Down
42 changes: 41 additions & 1 deletion src/dbus/gconnman_technology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ void Technology::setPowered(bool powered, PropertiesSetCallback callback) {
&Technology::finishAsyncCall, data.release());
}

void Technology::setTethering(bool tethering, PropertiesSetCallback callback) {
auto data = prepareCallback(std::move(callback));
setProperty(TETHERING_STR,
g_variant_new_boolean(static_cast<gboolean>(tethering)),
nullptr, &Technology::finishAsyncCall, data.release());
}

void Technology::setTetheringIdentifier(const std::string& identifier,
PropertiesSetCallback callback) {
auto data = prepareCallback(std::move(callback));
setProperty(TETHERINGIDENTIFIER_STR,
g_variant_new_string(identifier.c_str()), nullptr,
&Technology::finishAsyncCall, data.release());
}

void Technology::setTetheringPassphrase(const std::string& passphrase,
PropertiesSetCallback callback) {
auto data = prepareCallback(std::move(callback));
setProperty(TETHERINGPASSPHRASE_STR,
g_variant_new_string(passphrase.c_str()), nullptr,
&Technology::finishAsyncCall, data.release());
}

void Technology::setTetheringFreq(const uint32_t frequency,
PropertiesSetCallback callback) {
auto data = prepareCallback(std::move(callback));
setProperty(TETHERINGFREQ_STR, g_variant_new_uint32(frequency), nullptr,
&Technology::finishAsyncCall, data.release());
}

void Technology::scan(PropertiesSetCallback callback) {
auto data = prepareCallback(std::move(callback));
callMethod(nullptr, SCAN_STR, nullptr, &Technology::finishAsyncCall,
Expand All @@ -54,6 +84,10 @@ void TechProperties::update(const gchar* key, GVariant* value) {
tethering_ = g_variant_get_boolean(value) == 1U;
} else if (g_strcmp0(key, TETHERINGFREQ_STR) == 0U) {
tethering_freq_ = g_variant_get_int32(value);
Comment thread
EddyTheCo marked this conversation as resolved.
} else if (g_strcmp0(key, TETHERINGIDENTIFIER_STR) == 0U) {
tethering_identifier_ = g_variant_get_string(value, nullptr);
} else if (g_strcmp0(key, TETHERINGPASSPHRASE_STR) == 0U) {
tethering_passphrase_ = g_variant_get_string(value, nullptr);
} else {
LCM_LOG("Unknown property for Technology: " << key << '\n');
}
Expand All @@ -65,7 +99,13 @@ auto operator<<(std::ostream& ost, const TechProperties& obj) -> std::ostream& {
ost << POWERED_STR << ": " << std::boolalpha << obj.powered_ << '\n';
ost << CONNECTED_STR << ": " << std::boolalpha << obj.connected_ << '\n';
ost << TETHERING_STR << ": " << std::boolalpha << obj.tethering_ << '\n';
ost << TETHERINGFREQ_STR << ": " << obj.tethering_freq_ << " \n";
if (obj.type_ == TechProperties::Type::Wifi) {
ost << TETHERINGIDENTIFIER_STR << ": " << obj.tethering_identifier_
<< '\n';
ost << TETHERINGPASSPHRASE_STR << ": " << obj.tethering_passphrase_
<< '\n';
ost << TETHERINGFREQ_STR << ": " << obj.tethering_freq_ << " \n";
}
return ost;
}

Expand Down
Loading