diff options
-rw-r--r-- | src/accesspoint.vala | 37 | ||||
-rw-r--r-- | src/meson.build | 1 | ||||
-rw-r--r-- | src/network.vala | 13 | ||||
-rw-r--r-- | src/wifi.vala | 151 | ||||
-rw-r--r-- | src/wired.vala | 8 |
5 files changed, 148 insertions, 62 deletions
diff --git a/src/accesspoint.vala b/src/accesspoint.vala new file mode 100644 index 0000000..cc2eb4b --- /dev/null +++ b/src/accesspoint.vala @@ -0,0 +1,37 @@ +public class AstalNetwork.AccessPoint : Object { + private Wifi wifi; + private NM.AccessPoint ap; + + public uint bandwidth { get { return ap.bandwidth; } } + public string bssid { owned get { return ap.bssid; } } + public uint frequency { get { return ap.frequency; } } + public int last_seen { get { return ap.last_seen; } } + public uint max_bitrate { get { return ap.max_bitrate; } } + public uint8 strength { get { return ap.strength; } } + public NM.80211Mode mode { get { return ap.mode; } } + public NM.80211ApFlags flags { get { return ap.flags; } } + public NM.80211ApSecurityFlags rsn_flags { get { return ap.rsn_flags; } } + public NM.80211ApSecurityFlags wpa_flags { get { return ap.wpa_flags; } } + + public string? ssid { + owned get { + if (ap.ssid == null) + return null; + + return (string)NM.Utils.ssid_to_utf8(ap.ssid.get_data()); + } + } + + internal AccessPoint(Wifi wifi, NM.AccessPoint ap) { + this.wifi = wifi; + this.ap = ap; + ap.notify.connect((pspec) => { + if (get_class().find_property(pspec.name) != null) + notify_property(pspec.name); + }); + } + + // TODO: connect to ap + // public signal void auth(); + // public void try_connect(string? password) { } +} diff --git a/src/meson.build b/src/meson.build index c8138fb..3294ae3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -26,6 +26,7 @@ sources = [ 'wifi.vala', 'wired.vala', 'wired.vala', + 'accesspoint.vala', ] lib = library( diff --git a/src/network.vala b/src/network.vala index 53b3139..7c8e466 100644 --- a/src/network.vala +++ b/src/network.vala @@ -15,8 +15,8 @@ public class AstalNetwork.Network : Object { public NM.Client client { get; private set; } - public Wifi wifi { get; private set; } - public Wired wired { get; private set; } + public Wifi? wifi { get; private set; } + public Wired? wired { get; private set; } public Primary primary { get; private set; } public Connectivity connectivity { @@ -30,8 +30,13 @@ public class AstalNetwork.Network : Object { construct { try { client = new NM.Client(); - wifi = new Wifi((NM.DeviceWifi)get_device(NM.DeviceType.WIFI), client); - wired = new Wired((NM.DeviceEthernet)get_device(NM.DeviceType.ETHERNET), client); + var wifi_device = (NM.DeviceWifi)get_device(NM.DeviceType.WIFI); + if (wifi_device != null) + wifi = new Wifi(wifi_device); + + var ethernet = (NM.DeviceEthernet)get_device(NM.DeviceType.ETHERNET); + if (ethernet != null) + wired = new Wired(ethernet); sync(); client.notify["primary-connection"].connect(sync); diff --git a/src/wifi.vala b/src/wifi.vala index 8412a09..27cf27f 100644 --- a/src/wifi.vala +++ b/src/wifi.vala @@ -9,19 +9,55 @@ public class AstalNetwork.Wifi : Object { private const string ICON_DISABLED = "network-wireless-disabled-symbolic"; private const string ICON_OFFLINE = "network-wireless-offline-symbolic"; private const string ICON_NO_ROUTE = "network-wireless-no-route-symbolic"; + private const string ICON_HOTSPOT = "network-wireless-hotspot-symbolic"; - private NM.Client client; - public NM.DeviceWifi device { get; private set; } + private HashTable<string, AccessPoint> _access_points = + new HashTable<string, AccessPoint>(str_hash, str_equal); - public NM.ActiveConnection? connection; + public NM.DeviceWifi device { get; construct set; } + + public NM.ActiveConnection? active_connection { get; private set; } private ulong connection_handler = 0; - public NM.AccessPoint? access_point; + public AccessPoint? active_access_point { get; private set; } private ulong ap_handler = 0; - internal Wifi(NM.DeviceWifi device, NM.Client client) { + public List<weak AccessPoint> access_points { + owned get { return _access_points.get_values(); } + } + + public bool enabled { + get { return device.client.wireless_enabled; } + set { device.client.wireless_enabled = value; } + } + + public Internet internet { get; private set; } + public uint bandwidth { get; private set; } + public string ssid { get; private set; } + public uint8 strength { get; private set; } + public uint frequency { get; private set; } + public DeviceState state { get; private set; } + public string icon_name { get; private set; } + public bool is_hotspot { get; private set; } + public bool scanning { get; private set; } + + internal Wifi(NM.DeviceWifi device) { this.device = device; - this.client = client; + + foreach (var ap in device.access_points) + _access_points.set(ap.bssid, new AccessPoint(this, ap)); + + device.access_point_added.connect((access_point) => { + var ap = (NM.AccessPoint)access_point; + _access_points.set(ap.bssid, new AccessPoint(this, ap)); + notify_property("access-points"); + }); + + device.access_point_removed.connect((access_point) => { + var ap = (NM.AccessPoint)access_point; + _access_points.remove(ap.bssid); + notify_property("access-points"); + }); on_active_connection(); device.notify["active-connection"].connect(on_active_connection); @@ -30,16 +66,14 @@ public class AstalNetwork.Wifi : Object { device.notify["active-access-point"].connect(on_active_access_point); state = (DeviceState)device.state; - device.access_point_added.connect(() => notify_property("access-points")); - device.access_point_removed.connect(() => notify_property("access-points")); - client.notify["wireless-enabled"].connect(() => notify_property("enabled")); + device.client.notify["wireless-enabled"].connect(() => notify_property("enabled")); device.state_changed.connect((n, o, r) => { state_changed(n, o, r); state = (DeviceState)n; }); device.notify.connect(() => { icon_name = _icon(); }); - client.notify.connect(() => { icon_name = _icon(); }); + device.client.notify.connect(() => { icon_name = _icon(); }); icon_name = _icon(); } @@ -49,74 +83,79 @@ public class AstalNetwork.Wifi : Object { NM.DeviceStateReason reaseon ); + public void scan() { + scanning = true; + var last_scan = device.last_scan; + device.request_scan_async.begin(null, (_, res) => { + try { + device.request_scan_async.end(res); + Timeout.add(1000, () => { + if (device.last_scan == last_scan) + return Source.CONTINUE; + + scanning = false; + return Source.REMOVE; + }, Priority.DEFAULT); + } catch (Error err) { + critical(err.message); + } + }); + } + private void on_active_connection() { - if (connection_handler > 0 && connection != null) { - connection.disconnect(connection_handler); + if (connection_handler > 0 && active_connection != null) { + active_connection.disconnect(connection_handler); connection_handler = 0; - connection = null; + active_connection = null; } - connection = device.active_connection; - if (connection != null) { - connection_handler = connection.notify["state"].connect(() => { + active_connection = device.active_connection; + is_hotspot = _hotspot(); + if (active_connection != null) { + connection_handler = active_connection.notify["state"].connect(() => { internet = Internet.from_device(device); }); } } private void on_active_access_point_notify() { - bandwidth = access_point.bandwidth; - frequency = access_point.frequency; - strength = access_point.strength; - ssid = access_point.ssid; + bandwidth = active_access_point.bandwidth; + frequency = active_access_point.frequency; + strength = active_access_point.strength; + ssid = active_access_point.ssid; } private void on_active_access_point() { - if (ap_handler > 0 && access_point != null) { - access_point.disconnect(ap_handler); + if (ap_handler > 0 && active_access_point != null) { + active_access_point.disconnect(ap_handler); ap_handler = 0; - access_point = null; + active_access_point = null; } - access_point = device.active_access_point; - if (access_point != null) { + var ap = device.active_access_point; + if (ap != null) { + active_access_point = _access_points.get(ap.bssid); on_active_access_point_notify(); - ap_handler = access_point.notify.connect(on_active_access_point_notify); + ap_handler = active_access_point.notify.connect(on_active_access_point_notify); } } - public bool enabled { - get { return client.wireless_enabled; } - set { client.wireless_enabled = value; } - } - - public GenericArray<NM.AccessPoint> access_points { - get { return device.access_points; } - } - - public Internet internet { get; private set; } - public uint bandwidth { get; private set; } - public Bytes ssid { get; private set; } - public uint8 strength { get; private set; } - public uint frequency { get; private set; } - public DeviceState state { get; private set; } - public string icon_name { get; private set; } - private string _icon() { - var full = client.connectivity == NM.ConnectivityState.FULL; - if (!enabled) return ICON_DISABLED; + var full = device.client.connectivity == NM.ConnectivityState.FULL; + if (internet == Internet.CONNECTED) { + if (is_hotspot) return ICON_HOTSPOT; if (!full) return ICON_NO_ROUTE; + if (active_access_point == null) return ICON_CONNECTED; if (strength >= 80) return ICON_EXCELLENT; if (strength >= 60) return ICON_GOOD; if (strength >= 40) return ICON_OK; if (strength >= 20) return ICON_WEAK; - if (strength >= 0) return ICON_NONE; - return ICON_CONNECTED; + return ICON_NONE; } if (internet == Internet.CONNECTING) { @@ -125,13 +164,19 @@ public class AstalNetwork.Wifi : Object { return ICON_OFFLINE; } -} -namespace AstalNetwork { - public string ssid_to_string(Bytes? bytes) { - if (bytes == null) - return ""; + private bool _hotspot() { + if (device.active_connection == null) + return false; + + var conn = device.active_connection.connection; + if (conn == null) + return false; + + var ip4config = conn.get_setting_ip4_config(); + if (ip4config == null) + return false; - return (string)NM.Utils.ssid_to_utf8(bytes.get_data()); + return ip4config.method == NM.SettingIP4Config.METHOD_SHARED; } } diff --git a/src/wired.vala b/src/wired.vala index 4ff505f..68cf460 100644 --- a/src/wired.vala +++ b/src/wired.vala @@ -4,15 +4,13 @@ public class AstalNetwork.Wired : Object { private const string ICON_ACQUIRING = "network-wired-acquiring-symbolic"; private const string ICON_NO_ROUTE = "network-wired-no-route-symbolic"; - private NM.Client client; public NM.DeviceEthernet device { get; construct set; } public NM.ActiveConnection connection; private ulong connection_handler = 0; - internal Wired(NM.DeviceEthernet device, NM.Client client) { + internal Wired(NM.DeviceEthernet device) { this.device = device; - this.client = client; speed = device.speed; state = (DeviceState)device.state; @@ -31,7 +29,7 @@ public class AstalNetwork.Wired : Object { icon_name = _icon(); }); - client.notify.connect(() => { icon_name = _icon(); }); + device.client.notify.connect(() => { icon_name = _icon(); }); on_active_connection(); icon_name = _icon(); @@ -58,7 +56,7 @@ public class AstalNetwork.Wired : Object { public string icon_name { get; private set; } private string _icon() { - var full = client.connectivity == NM.ConnectivityState.FULL; + var full = device.client.connectivity == NM.ConnectivityState.FULL; if (internet == Internet.CONNECTING) { return ICON_ACQUIRING; |