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();
}
}
}