mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-02 20:12:07 +08:00
Tethering (#2676)
We can now enable tethering on the device. The user still has to reconnect to the wifi network after disabling tethering, the network manager is lazy. old-commit-hash: ec671d47412838b40cedab19e738e6227419590b
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "wifi.hpp"
|
||||
|
||||
#include "widgets/toggle.hpp"
|
||||
|
||||
void clearLayout(QLayout* layout) {
|
||||
while (QLayoutItem* item = layout->takeAt(0)) {
|
||||
@@ -30,9 +30,31 @@ WifiUI::WifiUI(QWidget *parent, int page_length) : QWidget(parent), networks_per
|
||||
|
||||
// Networks page
|
||||
wifi_widget = new QWidget;
|
||||
QVBoxLayout* networkLayout = new QVBoxLayout;
|
||||
QHBoxLayout *tethering_field = new QHBoxLayout;
|
||||
tethering_field->addWidget(new QLabel("Enable Tethering"));
|
||||
|
||||
Toggle* toggle_switch = new Toggle(this);
|
||||
toggle_switch->setFixedSize(150, 100);
|
||||
tethering_field->addWidget(toggle_switch);
|
||||
if (wifi->tetheringEnabled()){
|
||||
toggle_switch->togglePosition();
|
||||
}
|
||||
QObject::connect(toggle_switch, SIGNAL(stateChanged(int)), this, SLOT(toggleTethering(int)));
|
||||
|
||||
QWidget* tetheringWidget = new QWidget;
|
||||
tetheringWidget->setLayout(tethering_field);
|
||||
tetheringWidget->setFixedHeight(150);
|
||||
networkLayout->addWidget(tetheringWidget);
|
||||
|
||||
|
||||
vlayout = new QVBoxLayout;
|
||||
wifi_widget->setLayout(vlayout);
|
||||
swidget->addWidget(wifi_widget);
|
||||
networkLayout->addWidget(wifi_widget);
|
||||
|
||||
QWidget* networkWidget = new QWidget;
|
||||
networkWidget->setLayout(networkLayout);
|
||||
swidget->addWidget(networkWidget);
|
||||
|
||||
// Keyboard page
|
||||
input_field = new InputField();
|
||||
@@ -163,11 +185,19 @@ void WifiUI::refresh() {
|
||||
vlayout->addWidget(w);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WifiUI::toggleTethering(int enable){
|
||||
if(enable){
|
||||
wifi->enableTethering();
|
||||
}else{
|
||||
wifi->disableTethering();
|
||||
}
|
||||
}
|
||||
|
||||
void WifiUI::handleButton(QAbstractButton* button) {
|
||||
QPushButton* btn = static_cast<QPushButton*>(button);
|
||||
Network n = wifi->seen_networks[connectButtons->id(btn)];
|
||||
|
||||
input_field->setPromptText("Enter password for \"" + n.ssid + "\"");
|
||||
connectToNetwork(n);
|
||||
}
|
||||
|
||||
@@ -176,6 +206,7 @@ void WifiUI::connectToNetwork(Network n){
|
||||
if(n.security_type == SecurityType::OPEN){
|
||||
wifi->connect(n);
|
||||
} else if (n.security_type == SecurityType::WPA){
|
||||
input_field->setPromptText("Enter password for \"" + n.ssid + "\"");
|
||||
QString password = getStringFromUser();
|
||||
if(password.size()){
|
||||
wifi->connect(n, password);
|
||||
|
||||
@@ -15,7 +15,7 @@ class WifiUI : public QWidget {
|
||||
|
||||
public:
|
||||
int page;
|
||||
explicit WifiUI(QWidget *parent = 0, int page_length = 6);
|
||||
explicit WifiUI(QWidget *parent = 0, int page_length = 5);
|
||||
|
||||
private:
|
||||
WifiManager* wifi;
|
||||
@@ -30,12 +30,14 @@ private:
|
||||
QTimer *timer;
|
||||
QString text;
|
||||
QButtonGroup *connectButtons;
|
||||
bool tetheringEnabled;
|
||||
|
||||
void connectToNetwork(Network n);
|
||||
QString getStringFromUser();
|
||||
|
||||
private slots:
|
||||
void handleButton(QAbstractButton* m_button);
|
||||
void toggleTethering(int enable);
|
||||
void refresh();
|
||||
void receiveText(QString text);
|
||||
void wrongPassword(QString ssid);
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include "wifiManager.hpp"
|
||||
#include "common/params.h"
|
||||
|
||||
/**
|
||||
* We are using a NetworkManager DBUS API : https://developer.gnome.org/NetworkManager/1.26/spec.html
|
||||
* */
|
||||
|
||||
|
||||
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags
|
||||
const int NM_802_11_AP_FLAGS_PRIVACY = 0x00000001;
|
||||
|
||||
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags
|
||||
const int NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001;
|
||||
const int NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002;
|
||||
const int NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010;
|
||||
const int NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020;
|
||||
const int NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100;
|
||||
const int NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200;
|
||||
|
||||
|
||||
QString nm_path = "/org/freedesktop/NetworkManager";
|
||||
QString nm_settings_path = "/org/freedesktop/NetworkManager/Settings";
|
||||
|
||||
@@ -40,12 +55,14 @@ bool compare_by_strength(const Network &a, const Network &b){
|
||||
return a.strength > b.strength;
|
||||
}
|
||||
|
||||
|
||||
WifiManager::WifiManager(){
|
||||
qDBusRegisterMetaType<Connection>();
|
||||
qDBusRegisterMetaType<IpConfig>();
|
||||
connecting_to_network = "";
|
||||
adapter = get_adapter();
|
||||
has_adapter = adapter != "";
|
||||
if(has_adapter){
|
||||
if (has_adapter){
|
||||
QDBusInterface nm(nm_service, adapter, device_iface, bus);
|
||||
bus.connect(nm_service, adapter, device_iface, "StateChanged", this, SLOT(change(unsigned int, unsigned int, unsigned int)));
|
||||
|
||||
@@ -54,6 +71,13 @@ WifiManager::WifiManager(){
|
||||
raw_adapter_state = get_response<uint>(response);
|
||||
change(raw_adapter_state, 0, 0);
|
||||
}
|
||||
|
||||
// Compute tethering ssid as "Weedle" + first 4 characters of a dongle id
|
||||
tethering_ssid = "weedle";
|
||||
std::string bytes = Params().get("DongleId");
|
||||
if (bytes.length() >= 4){
|
||||
tethering_ssid+="-"+QString::fromStdString(bytes.substr(0,4));
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::refreshNetworks(){
|
||||
@@ -64,7 +88,7 @@ void WifiManager::refreshNetworks(){
|
||||
seen_ssids.clear();
|
||||
|
||||
for (Network &network : get_networks()){
|
||||
if(seen_ssids.count(network.ssid)){
|
||||
if (seen_ssids.count(network.ssid)){
|
||||
continue;
|
||||
}
|
||||
seen_ssids.push_back(network.ssid);
|
||||
@@ -89,12 +113,12 @@ QList<Network> WifiManager::get_networks(){
|
||||
unsigned int strength = get_ap_strength(path.path());
|
||||
SecurityType security = getSecurityType(path.path());
|
||||
ConnectedType ctype;
|
||||
if(path.path() != active_ap){
|
||||
if (path.path() != active_ap){
|
||||
ctype = ConnectedType::DISCONNECTED;
|
||||
}else{
|
||||
if(ssid == connecting_to_network){
|
||||
}else {
|
||||
if (ssid == connecting_to_network){
|
||||
ctype = ConnectedType::CONNECTING;
|
||||
}else{
|
||||
}else {
|
||||
ctype = ConnectedType::CONNECTED;
|
||||
}
|
||||
}
|
||||
@@ -116,9 +140,12 @@ SecurityType WifiManager::getSecurityType(QString path){
|
||||
int rsnflag = get_property(path, "RsnFlags").toInt();
|
||||
int wpa_props = wpaflag | rsnflag;
|
||||
|
||||
if(sflag == 0){
|
||||
// obtained by looking at flags of networks in the office as reported by an Android phone
|
||||
const int supports_wpa = NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK;
|
||||
|
||||
if (sflag == 0){
|
||||
return SecurityType::OPEN;
|
||||
} else if((sflag & 0x1) && (wpa_props & (0x333) && !(wpa_props & 0x200))) {
|
||||
} else if ((sflag & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_props & supports_wpa) && !(wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
|
||||
return SecurityType::WPA;
|
||||
} else {
|
||||
return SecurityType::UNSUPPORTED;
|
||||
@@ -135,10 +162,7 @@ void WifiManager::connect(Network n, QString password){
|
||||
|
||||
void WifiManager::connect(Network n, QString username, QString password){
|
||||
connecting_to_network = n.ssid;
|
||||
QString active_ap = get_active_ap();
|
||||
if(active_ap!="" && active_ap!="/"){
|
||||
deactivate_connections(get_property(active_ap, "Ssid")); //Disconnect from any connected networks
|
||||
}
|
||||
disconnect();
|
||||
clear_connections(n.ssid); //Clear all connections that may already exist to the network we are connecting
|
||||
connect(n.ssid, username, password, n.security_type);
|
||||
}
|
||||
@@ -147,13 +171,13 @@ void WifiManager::connect(QByteArray ssid, QString username, QString password, S
|
||||
Connection connection;
|
||||
connection["connection"]["type"] = "802-11-wireless";
|
||||
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
|
||||
|
||||
connection["connection"]["id"] = "OpenPilot connection "+QString::fromStdString(ssid.toStdString());
|
||||
connection["connection"]["autoconnect-retries"] = 0;
|
||||
|
||||
connection["802-11-wireless"]["ssid"] = ssid;
|
||||
connection["802-11-wireless"]["mode"] = "infrastructure";
|
||||
|
||||
if(security_type == SecurityType::WPA){
|
||||
if (security_type == SecurityType::WPA){
|
||||
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
|
||||
connection["802-11-wireless-security"]["auth-alg"] = "open";
|
||||
connection["802-11-wireless-security"]["psk"] = password;
|
||||
@@ -163,16 +187,16 @@ void WifiManager::connect(QByteArray ssid, QString username, QString password, S
|
||||
connection["ipv6"]["method"] = "ignore";
|
||||
|
||||
QDBusInterface nm_settings(nm_service, nm_settings_path, nm_settings_iface, bus);
|
||||
QDBusReply<QDBusObjectPath> result = nm_settings.call("AddConnection", QVariant::fromValue(connection));
|
||||
nm_settings.call("AddConnection", QVariant::fromValue(connection));
|
||||
}
|
||||
|
||||
void WifiManager::deactivate_connections(QString ssid){
|
||||
for(QDBusObjectPath active_connection_raw : get_active_connections()){
|
||||
for (QDBusObjectPath active_connection_raw : get_active_connections()){
|
||||
QString active_connection = active_connection_raw.path();
|
||||
QDBusInterface nm(nm_service, active_connection, props_iface, bus);
|
||||
QDBusObjectPath pth = get_response<QDBusObjectPath>(nm.call("Get", connection_iface, "SpecificObject"));
|
||||
QString Ssid = get_property(pth.path(), "Ssid");
|
||||
if(Ssid == ssid){
|
||||
if (Ssid == ssid){
|
||||
QDBusInterface nm2(nm_service, nm_path, nm_iface, bus);
|
||||
nm2.call("DeactivateConnection", QVariant::fromValue(active_connection_raw));
|
||||
}
|
||||
@@ -210,12 +234,12 @@ void WifiManager::clear_connections(QString ssid){
|
||||
|
||||
QMap<QString,QMap<QString,QVariant> > map;
|
||||
dbusArg >> map;
|
||||
for(QString outer_key : map.keys()) {
|
||||
for (QString outer_key : map.keys()) {
|
||||
QMap<QString,QVariant> innerMap = map.value(outer_key);
|
||||
for(QString inner_key : innerMap.keys()) {
|
||||
if(inner_key == "ssid"){
|
||||
for (QString inner_key : innerMap.keys()) {
|
||||
if (inner_key == "ssid"){
|
||||
QString value = innerMap.value(inner_key).value<QString>();
|
||||
if(value == ssid){
|
||||
if (value == ssid){
|
||||
nm2.call("Delete");
|
||||
}
|
||||
}
|
||||
@@ -288,9 +312,58 @@ QString WifiManager::get_adapter(){
|
||||
|
||||
void WifiManager::change(unsigned int new_state,unsigned int previous_state,unsigned int change_reason){
|
||||
raw_adapter_state = new_state;
|
||||
if(new_state == state_need_auth && change_reason == reason_wrong_password){
|
||||
if (new_state == state_need_auth && change_reason == reason_wrong_password){
|
||||
emit wrongPassword(connecting_to_network);
|
||||
}else if(new_state == state_connected){
|
||||
connecting_to_network="";
|
||||
}else if (new_state == state_connected){
|
||||
connecting_to_network = "";
|
||||
}
|
||||
}
|
||||
|
||||
void WifiManager::disconnect(){
|
||||
QString active_ap = get_active_ap();
|
||||
if (active_ap!="" && active_ap!="/"){
|
||||
deactivate_connections(get_property(active_ap, "Ssid"));
|
||||
}
|
||||
}
|
||||
|
||||
//Functions for tethering
|
||||
|
||||
void WifiManager::enableTethering(){
|
||||
disconnect();
|
||||
Connection connection;
|
||||
connection["connection"]["id"] = "Hotspot";
|
||||
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
|
||||
connection["connection"]["type"] = "802-11-wireless";
|
||||
connection["connection"]["interface-name"] = "wlan0";
|
||||
|
||||
connection["802-11-wireless"]["band"] = "bg";
|
||||
connection["802-11-wireless"]["mode"] = "ap";
|
||||
connection["802-11-wireless"]["ssid"] = tethering_ssid.toUtf8();
|
||||
|
||||
connection["802-11-wireless-security"]["group"] = QStringList("ccmp");
|
||||
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
|
||||
connection["802-11-wireless-security"]["pairwise"] = QStringList("ccmp");
|
||||
connection["802-11-wireless-security"]["proto"] = QStringList("rsn");
|
||||
connection["802-11-wireless-security"]["psk"] = "swagswagcomma";
|
||||
|
||||
connection["ipv4"]["method"] = "shared";
|
||||
QMap<QString,QVariant> adress1;
|
||||
adress1["address"] = "192.168.43.1";
|
||||
adress1["prefix"] = 24u;
|
||||
connection["ipv4"]["address-data"] = QVariant::fromValue(IpConfig() << adress1);
|
||||
connection["ipv4"]["gateway"] = "192.168.43.1";
|
||||
connection["ipv6"]["method"] = "ignore";
|
||||
|
||||
QDBusInterface nm_settings(nm_service, nm_settings_path, nm_settings_iface, bus);
|
||||
nm_settings.call("AddConnection", QVariant::fromValue(connection));
|
||||
|
||||
}
|
||||
|
||||
void WifiManager::disableTethering(){
|
||||
clear_connections(tethering_ssid);
|
||||
}
|
||||
|
||||
bool WifiManager::tetheringEnabled(){
|
||||
QString active_ap = get_active_ap();
|
||||
return get_property(active_ap, "Ssid") == tethering_ssid;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ enum class ConnectedType{
|
||||
};
|
||||
|
||||
typedef QMap<QString, QMap<QString, QVariant>> Connection;
|
||||
typedef QVector<QMap<QString, QVariant>> IpConfig;
|
||||
|
||||
struct Network {
|
||||
QString path;
|
||||
@@ -37,6 +38,11 @@ public:
|
||||
void connect(Network ssid);
|
||||
void connect(Network ssid, QString password);
|
||||
void connect(Network ssid, QString username, QString password);
|
||||
// Tethering functions
|
||||
|
||||
void enableTethering();
|
||||
void disableTethering();
|
||||
bool tetheringEnabled();
|
||||
|
||||
private:
|
||||
QVector<QByteArray> seen_ssids;
|
||||
@@ -44,6 +50,7 @@ private:
|
||||
QDBusConnection bus = QDBusConnection::systemBus();
|
||||
unsigned int raw_adapter_state;//Connection status https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMDeviceState
|
||||
QString connecting_to_network;
|
||||
QString tethering_ssid;
|
||||
|
||||
QString get_adapter();
|
||||
QList<Network> get_networks();
|
||||
@@ -56,6 +63,7 @@ private:
|
||||
QByteArray get_property(QString network_path, QString property);
|
||||
unsigned int get_ap_strength(QString network_path);
|
||||
SecurityType getSecurityType(QString ssid);
|
||||
void disconnect();
|
||||
|
||||
private slots:
|
||||
void change(unsigned int new_state, unsigned int previous_state, unsigned int change_reason);
|
||||
|
||||
Reference in New Issue
Block a user