From cd980350e41a14be04626ab3867a50ac4e962545 Mon Sep 17 00:00:00 2001 From: takotori Date: Sat, 2 Dec 2023 12:24:16 +0100 Subject: [PATCH] Implement wifiaddressentry --- Cargo.toml | 3 +- src/components/wifi/utils.rs | 9 +- src/components/wifi/wifiAddressEntry.rs | 139 +++++++- src/components/wifi/wifiAddressEntryImpl.rs | 14 +- src/components/wifi/wifiOptions.rs | 343 ++++++++++---------- src/components/wifi/wifiOptionsImpl.rs | 2 + src/components/wifi/wifiRouteEntry.rs | 44 ++- src/resources/resetUI.cmb | 9 +- src/resources/resetWifiAddressEntry.ui | 6 +- src/resources/resetWifiOptions.ui | 5 + 10 files changed, 362 insertions(+), 212 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1102a34..e72b38f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,8 @@ tokio = { version = "1.33.0", features = [ "sync", ] } fork = "0.1.22" -regex = "1.10.2" +ipnetwork = "0.20.0" +once_cell = "1.18.0" [build-dependencies] glib-build-tools = "0.18.0" diff --git a/src/components/wifi/utils.rs b/src/components/wifi/utils.rs index b6e74b6..c15341d 100644 --- a/src/components/wifi/utils.rs +++ b/src/components/wifi/utils.rs @@ -6,8 +6,15 @@ use std::collections::HashMap; use std::time::Duration; use ReSet_Lib::network::connection::Connection as ResetConnection; +#[derive(Default, Copy, Clone)] +pub enum IpProtocol { + #[default] + IPv4, + IPv6, +} + type ResultType = - Result<(HashMap>>>,), Error>; +Result<(HashMap>>>,), Error>; pub fn getConnectionSettings(path: Path<'static>) -> ResetConnection { let conn = Connection::new_session().unwrap(); diff --git a/src/components/wifi/wifiAddressEntry.rs b/src/components/wifi/wifiAddressEntry.rs index bed43e2..844c561 100644 --- a/src/components/wifi/wifiAddressEntry.rs +++ b/src/components/wifi/wifiAddressEntry.rs @@ -1,12 +1,19 @@ +use std::cell::RefCell; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::rc::Rc; +use std::str::FromStr; + use adw::glib; use adw::glib::Object; use adw::prelude::PreferencesRowExt; +use glib::clone; use glib::subclass::prelude::ObjectSubclassIsExt; -use gtk::prelude::EditableExt; -use ReSet_Lib::network::connection::Address; +use gtk::prelude::{ButtonExt, EditableExt, WidgetExt}; +use ReSet_Lib::network::connection::{Address, Connection}; +use crate::components::wifi::utils::IpProtocol; use crate::components::wifi::wifiAddressEntryImpl; -use crate::components::wifi::wifiOptions::getValueFromKey; +use crate::components::wifi::wifiAddressEntryImpl::WifiAddressEntryImpl; glib::wrapper! { pub struct WifiAddressEntry(ObjectSubclass) @@ -15,22 +22,126 @@ glib::wrapper! { } impl WifiAddressEntry { - pub fn new(address: Option<&Address>) -> Self { + pub fn new(address: Option, conn: Rc>, protocol: IpProtocol) -> Self { let entry: WifiAddressEntry = Object::builder().build(); + let entryImp = entry.imp(); if let Some(address) = address { - let entryImp = entry.imp(); - let map = address.to_map(); + let conn = conn.borrow(); + let address = unsafe { conn.ipv4.address_data.get_unchecked(address) }; - let addr = getValueFromKey(&map, "address"); - let prefix = getValueFromKey(&map, "prefix-length"); - - entryImp.resetAddressAddress.set_text(&addr); - entryImp.resetAddressNetmask.set_text(&prefix); - entryImp - .resetAddressRow - .set_title(&format!("{}, {}", addr, prefix)); + entryImp.resetAddressAddress.set_text(&*address.address); + entryImp.resetAddressPrefix.set_text(&*address.prefix_length.to_string()); + entryImp.resetAddressRow.set_title(&format!("{}, {}", &*address.address, address.prefix_length)); } + entryImp.protocol.set(protocol); + entry.setupCallbacks(conn); entry } + + pub fn setupCallbacks(&self, connection: Rc>) { + let selfImp = self.imp(); + + let conn = connection.clone(); + selfImp.resetAddressAddress.connect_changed(clone!(@weak selfImp, @weak self as what => move |entry| { + let addressInput = entry.text(); + let mut conn = conn.borrow_mut(); + + if addressInput.is_empty() { + selfImp.resetAddressAddress.remove_css_class("error"); + selfImp.resetAddressRow.set_title("Add new address"); + return; + } + let result = match selfImp.protocol.get() { + IpProtocol::IPv4 => Ipv4Addr::from_str(addressInput.as_str()).map(|a| IpAddr::V4(a)), + IpProtocol::IPv6 => Ipv6Addr::from_str(addressInput.as_str()).map(|a| IpAddr::V6(a)), + }; + match result { + Ok(ip_addr) => { + selfImp.resetAddressAddress.remove_css_class("error"); + let addressData = match selfImp.protocol.get() { + IpProtocol::IPv4 => &mut conn.ipv4.address_data, + IpProtocol::IPv6 => &mut conn.ipv6.address_data, + }; + addressData.push(Address::theBetterNew(ip_addr.to_string(), selfImp.prefix.get().1 as u32)); + *selfImp.address.borrow_mut() = (true, ip_addr.to_string()); + } + Err(_) => { + selfImp.resetAddressAddress.add_css_class("error"); + *selfImp.address.borrow_mut() = (false, String::default()); + } + } + setRowName(&selfImp); + })); + + let conn = connection.clone(); + selfImp.resetAddressPrefix.connect_changed(clone!(@weak selfImp => move |entry| { + let prefixInput = entry.text(); + let prefix = prefixInput.parse::(); + let mut conn = conn.borrow_mut(); + + let handleError = || { + if selfImp.resetAddressPrefix.text().is_empty() { + selfImp.resetAddressPrefix.remove_css_class("error"); + } else { + selfImp.resetAddressPrefix.add_css_class("error"); + } + selfImp.prefix.set((false, 0)); + setRowName(&selfImp); + return; + }; + + if prefixInput.is_empty() || !prefix.is_ok() { + handleError(); + return; + } + + let prefix = prefix.unwrap(); + match selfImp.protocol.get() { + IpProtocol::IPv4 if prefix < 32 => { + selfImp.prefix.set((true, prefix as u32)); + selfImp.resetAddressPrefix.remove_css_class("error"); + if let Ok(address2) = Ipv4Addr::from_str(selfImp.resetAddressAddress.text().as_str()) { + if let Some(addr) = conn.ipv4.address_data.iter_mut() + .find(|connAddr| *connAddr.address == address2.to_string()) { + addr.prefix_length = prefix as u32; + } + } + } + IpProtocol::IPv6 if prefix < 128 => { + selfImp.prefix.set((true, prefix as u32)); + selfImp.resetAddressPrefix.remove_css_class("error"); + if let Ok(address2) = Ipv6Addr::from_str(selfImp.resetAddressAddress.text().as_str()) { + if let Some(addr) = conn.ipv6.address_data.iter_mut() + .find(|connAddr| *connAddr.address == address2.to_string()) { + addr.prefix_length = prefix as u32; + } + } + } + _ => handleError() + } + setRowName(&selfImp); + })); + + let conn = connection.clone(); + selfImp.resetAddressRemove.connect_clicked(clone!(@weak selfImp, @weak self as what => move |_| { + let address = selfImp.resetAddressAddress.text(); + let mut conn = conn.borrow_mut(); + conn.ipv4.address_data.retain(|addr| addr.address != address.to_string()); + what.unparent(); + })); + } } + +fn setRowName(selfImp: &WifiAddressEntryImpl) { + if selfImp.resetAddressAddress.text().is_empty() { return; } + let address = selfImp.address.borrow(); + let prefix = selfImp.prefix.get(); + let title = match (address.0, prefix.0) { + (true, true) => { format!("{}/{}", address.1, prefix.1) }, + (true, false) => "Prefix wrong".to_string(), + (false, true) => "Address wrong".to_string(), + (false, false) => "Address and Prefix wrong".to_string(), + }; + selfImp.resetAddressRow.set_title(&*title); +} \ No newline at end of file diff --git a/src/components/wifi/wifiAddressEntryImpl.rs b/src/components/wifi/wifiAddressEntryImpl.rs index 4f68f31..2a5a911 100644 --- a/src/components/wifi/wifiAddressEntryImpl.rs +++ b/src/components/wifi/wifiAddressEntryImpl.rs @@ -1,7 +1,12 @@ -use crate::components::wifi::wifiAddressEntry; +use std::cell::{Cell, RefCell}; use adw::{EntryRow, ExpanderRow}; +use glib::once_cell::sync::Lazy; +use glib::StaticType; +use glib::subclass::Signal; +use crate::components::wifi::{wifiAddressEntry}; use gtk::subclass::prelude::*; -use gtk::{glib, Button, CompositeTemplate}; +use gtk::{glib, CompositeTemplate, Button}; +use crate::components::wifi::utils::IpProtocol; #[allow(non_snake_case)] #[derive(Default, CompositeTemplate)] @@ -12,9 +17,12 @@ pub struct WifiAddressEntryImpl { #[template_child] pub resetAddressAddress: TemplateChild, #[template_child] - pub resetAddressNetmask: TemplateChild, + pub resetAddressPrefix: TemplateChild, #[template_child] pub resetAddressRemove: TemplateChild