using System; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using Vinno.FIS.Sonopost.Wireless.Win32; using Vinno.FIS.Sonopost.Wireless.Win32.Interop; namespace Vinno.FIS.Sonopost.Wireless { public class AccessPoint { private WlanInterface _interface; private WlanAvailableNetwork _network; internal AccessPoint(WlanInterface interfac, WlanAvailableNetwork network) { _interface = interfac; _network = network; } public string Name { get { var str = Encoding.UTF8.GetString(_network.dot11Ssid.SSID, 0, (int)_network.dot11Ssid.SSIDLength); if (string.IsNullOrWhiteSpace(str)) { return "Others"; } return str; } } public uint SignalStrength { get { return _network.wlanSignalQuality; } } /// /// If the computer has a connection profile stored for this access point /// public bool HasProfile { get { try { return _interface.GetProfiles().Where(p => p.profileName == Name).Any(); } catch { return false; } } } public bool IsSecure { get { return _network.securityEnabled; } } public bool IsConnected { get { try { var a = _interface.CurrentConnection; // This prop throws exception if not connected, which forces me to this try catch. Refactor plix. return a.profileName == _network.profileName; } catch { return false; } } } /// /// Returns the underlying network object. /// internal WlanAvailableNetwork Network { get { return _network; } } /// /// Returns the underlying interface object. /// internal WlanInterface Interface { get { return _interface; } } /// /// Checks that the password format matches this access point's encryption method. /// public bool IsValidPassword(string password) { return PasswordHelper.IsValid(password, _network.dot11DefaultCipherAlgorithm); } /// /// Connect synchronous to the access point. /// public bool Connect(AuthRequest request, bool overwriteProfile = false) { // No point to continue with the connect if the password is not valid if overwrite is true or profile is missing. if (!request.IsPasswordValid && (!HasProfile || overwriteProfile)) return false; // If we should create or overwrite the profile, do so. if (!HasProfile || overwriteProfile) { if (HasProfile) _interface.DeleteProfile(Name); request.Process(); } // TODO: Auth algorithm: IEEE80211_Open + Cipher algorithm: None throws an error. // Probably due to connectionmode profile + no profile exist, cant figure out how to solve it though. return _interface.ConnectSynchronously(WlanConnectionMode.Profile, _network.dot11BssType, Name, 6000); } /// /// Connect asynchronous to the access point. /// public void ConnectAsync(AuthRequest request, bool overwriteProfile = false, Action onConnectComplete = null) { // TODO: Refactor -> Use async connect in wlaninterface. ThreadPool.QueueUserWorkItem(new WaitCallback((o) => { bool success = false; try { success = Connect(request, overwriteProfile); } catch (Win32Exception) { success = false; } if (onConnectComplete != null) onConnectComplete(success); })); } public string GetProfileXML() { if (HasProfile) return _interface.GetProfileXml(Name); else return string.Empty; } public void DeleteProfile() { try { if (HasProfile) _interface.DeleteProfile(Name); } catch { } } public override sealed string ToString() { StringBuilder info = new StringBuilder(); info.AppendLine("Interface: " + _interface.InterfaceName); info.AppendLine("Auth algorithm: " + _network.dot11DefaultAuthAlgorithm); info.AppendLine("Cipher algorithm: " + _network.dot11DefaultCipherAlgorithm); info.AppendLine("BSS type: " + _network.dot11BssType); info.AppendLine("Connectable: " + _network.networkConnectable); if (!_network.networkConnectable) info.AppendLine("Reason to false: " + _network.wlanNotConnectableReason); return info.ToString(); } public object Clone() { return MemberwiseClone(); } } }