SEBWIN-788: Implemented automatic connection attempt and retry on invalid credentials. Improved wording of username label in credentials dialog.

This commit is contained in:
Damian Büchel 2024-06-03 19:41:54 +02:00
parent b3228aedef
commit 84bbcb82ef
12 changed files with 99 additions and 61 deletions

View file

@ -106,7 +106,7 @@
Benutzername:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Benutzername (optional):
Benutzername (falls erforderlich):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Bitte geben Sie die erforderlichen Anmeldeinformationen ein, um eine Verbindung mit dem drahtlosen Netzwerk "%%_NAME_%%" herzustellen.

View file

@ -106,7 +106,7 @@
Username:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Username (optional):
Username (if required):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Please enter the required credentials to establish a connection to the wireless network "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
Nombre de usuario:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Nombre de usuario (opcional):
Nombre de usuario (si se requiere):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Por favor, introduzca las credenciales necesarias para establecer una conexión con la red inalámbrica "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
Kasutajanimi:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Kasutajanimi (vabatahtlik):
Kasutajanimi (kui see on nõutav):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Palun sisestage vajalikud volitused, et luua ühendus traadita võrguga "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
Nom d'utilisateur:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Nom d'utilisateur (facultatif):
Nom d'utilisateur (si requis):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Veuillez saisir les informations d'identification requises pour établir une connexion au réseau sans fil "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
Nama pengguna:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Nama pengguna (opsional):
Nama pengguna (jika diperlukan):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Masukkan kredensial yang diperlukan untuk membuat sambungan ke jaringan nirkabel "%%_NAMA_%%".

View file

@ -106,7 +106,7 @@
Nome utente:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Nome utente (facoltativo):
Nome utente (se richiesto):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Inserire le credenziali richieste per stabilire una connessione alla rete wireless "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
Gebruikersnaam:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Gebruikersnaam (optioneel):
Gebruikersnaam (indien vereist):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Voer de vereiste gegevens in om verbinding te maken met het draadloze netwerk “%%_NAME_%%”.

View file

@ -106,7 +106,7 @@
Имя пользователя:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
Имя пользователя (необязательно):
Имя пользователя (если требуется):
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
Введите необходимые учетные данные для установления соединения с беспроводной сетью "%%_NAME_%%".

View file

@ -106,7 +106,7 @@
用户名:
</Entry>
<Entry key="CredentialsDialog_UsernameOptionalLabel">
用户名(可选
用户名(如需要
</Entry>
<Entry key="CredentialsDialog_WirelessNetworkMessage">
请输入与无线网络 "%%_NAME_%%" 建立连接所需的凭证。

View file

@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using Windows.Devices.WiFi;
using Windows.Networking.Connectivity;
namespace SafeExamBrowser.SystemComponents.Network
{
@ -21,6 +22,16 @@ namespace SafeExamBrowser.SystemComponents.Network
return networks.Where(n => !string.IsNullOrEmpty(n.Ssid)).GroupBy(n => n.Ssid).Select(g => g.First()).OrderBy(n => n.Ssid);
}
internal static bool IsOpen(this WiFiAvailableNetwork network)
{
return network.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Open80211 && network.SecuritySettings.NetworkEncryptionType == NetworkEncryptionType.None;
}
internal static string ToLogString(this WiFiAvailableNetwork network)
{
return $"'{network.Ssid}' ({network.SecuritySettings.NetworkAuthenticationType}, {network.SecuritySettings.NetworkEncryptionType})";
}
internal static WirelessNetwork ToWirelessNetwork(this WiFiAvailableNetwork network)
{
return new WirelessNetwork

View file

@ -7,9 +7,11 @@
*/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Network;
using SafeExamBrowser.SystemComponents.Contracts.Network.Events;
@ -27,12 +29,13 @@ namespace SafeExamBrowser.SystemComponents.Network
{
private readonly object @lock = new object();
private readonly ConcurrentDictionary<string, object> attempts;
private readonly ILogger logger;
private readonly INativeMethods nativeMethods;
private readonly List<WirelessNetwork> wirelessNetworks;
private Timer timer;
private WiFiAdapter adapter;
private Timer timer;
private bool HasWirelessAdapter => adapter != default;
@ -44,6 +47,7 @@ namespace SafeExamBrowser.SystemComponents.Network
public NetworkAdapter(ILogger logger, INativeMethods nativeMethods)
{
this.attempts = new ConcurrentDictionary<string, object>();
this.logger = logger;
this.nativeMethods = nativeMethods;
this.wirelessNetworks = new List<WirelessNetwork>();
@ -51,6 +55,7 @@ namespace SafeExamBrowser.SystemComponents.Network
public void ConnectToWirelessNetwork(string name)
{
var isFirstAttempt = !attempts.TryGetValue(name, out _);
var network = default(WiFiAvailableNetwork);
lock (@lock)
@ -60,29 +65,21 @@ namespace SafeExamBrowser.SystemComponents.Network
if (network != default)
{
var isOpen = network.SecuritySettings.NetworkAuthenticationType == NetworkAuthenticationType.Open80211 && network.SecuritySettings.NetworkEncryptionType == NetworkEncryptionType.None;
if (isOpen)
if (isFirstAttempt || network.IsOpen())
{
logger.Info($"Attempting to connect to open wireless network '{name}'...");
adapter.ConnectAsync(network, WiFiReconnectionKind.Automatic).Completed = (o, s) => Adapter_ConnectCompleted(name, o, s);
Status = ConnectionStatus.Connecting;
ConnectAutomatically(network);
}
else if (TryGetCredentials(name, out var credentials))
else
{
logger.Info($"Attempting to connect to wireless network '{name}' with credentials...");
adapter.ConnectAsync(network, WiFiReconnectionKind.Automatic, credentials).Completed = (o, s) => Adapter_ConnectCompleted(name, o, s);
Status = ConnectionStatus.Connecting;
ConnectWithAuthentication(network);
}
Changed?.Invoke();
}
else
{
logger.Warn($"Could not find wireless network '{name}'!");
}
Changed?.Invoke();
}
public IEnumerable<IWirelessNetwork> GetWirelessNetworks()
@ -146,6 +143,68 @@ namespace SafeExamBrowser.SystemComponents.Network
logger.Info("Stopped monitoring the network adapter.");
}
private void Adapter_AvailableNetworksChanged(WiFiAdapter sender, object args)
{
Update(false);
}
private void Adapter_ConnectCompleted(WiFiAvailableNetwork network, IAsyncOperation<WiFiConnectionResult> operation, AsyncStatus status)
{
var connectionStatus = default(WiFiConnectionStatus?);
if (status == AsyncStatus.Completed)
{
connectionStatus = operation.GetResults()?.ConnectionStatus;
}
else
{
logger.Error($"Failed to complete connection operation! Status: {status}.");
}
if (connectionStatus == WiFiConnectionStatus.Success)
{
attempts.TryRemove(network.Ssid, out _);
logger.Info($"Successfully connected to wireless network {network.ToLogString()}.");
}
else if (connectionStatus == WiFiConnectionStatus.InvalidCredential)
{
attempts.TryAdd(network.Ssid, default);
logger.Info($"Failed to connect to wireless network {network.ToLogString()} due to invalid credentials. Retrying...");
Task.Run(() => ConnectToWirelessNetwork(network.Ssid));
}
else
{
Status = ConnectionStatus.Disconnected;
logger.Error($"Failed to connect to wireless network {network.ToLogString()}! Reason: {connectionStatus}.");
}
Update();
}
private void ConnectAutomatically(WiFiAvailableNetwork network)
{
logger.Info($"Attempting to automatically connect to {(network.IsOpen() ? "open" : "protected")} wireless network {network.ToLogString()}...");
adapter.ConnectAsync(network, WiFiReconnectionKind.Automatic).Completed = (o, s) => Adapter_ConnectCompleted(network, o, s);
Status = ConnectionStatus.Connecting;
}
private void ConnectWithAuthentication(WiFiAvailableNetwork network)
{
if (TryGetCredentials(network.Ssid, out var credentials))
{
logger.Info($"Attempting to connect to protected wirless network {network.ToLogString()}...");
adapter.ConnectAsync(network, WiFiReconnectionKind.Automatic, credentials).Completed = (o, s) => Adapter_ConnectCompleted(network, o, s);
Status = ConnectionStatus.Connecting;
}
else
{
Status = ConnectionStatus.Disconnected;
Update();
}
}
private void InitializeAdapter()
{
try
@ -188,38 +247,6 @@ namespace SafeExamBrowser.SystemComponents.Network
}
}
private void Adapter_AvailableNetworksChanged(WiFiAdapter sender, object args)
{
Update(false);
}
private void Adapter_ConnectCompleted(string name, IAsyncOperation<WiFiConnectionResult> operation, AsyncStatus status)
{
var connectionStatus = default(WiFiConnectionStatus?);
if (status == AsyncStatus.Completed)
{
connectionStatus = operation.GetResults()?.ConnectionStatus;
}
else
{
logger.Error($"Failed to complete connection operation! Status: {status}.");
}
if (connectionStatus == WiFiConnectionStatus.Success)
{
Status = ConnectionStatus.Connected;
logger.Info($"Successfully connected to wireless network '{name}'.");
}
else
{
Status = ConnectionStatus.Disconnected;
logger.Error($"Failed to connect to wireless network '{name}'! Reason: {connectionStatus}.");
}
Update();
}
private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
logger.Debug("Network address changed.");
@ -292,7 +319,7 @@ namespace SafeExamBrowser.SystemComponents.Network
{
lock (@lock)
{
var hasInternet = nativeMethods.HasInternetConnection();
var hasConnection = nativeMethods.HasInternetConnection();
var isConnecting = Status == ConnectionStatus.Connecting;
var previousStatus = Status;
@ -300,7 +327,7 @@ namespace SafeExamBrowser.SystemComponents.Network
if (HasWirelessAdapter)
{
TryGetCurrentWirelessNetwork(out var currentNetwork);
hasConnection &= TryGetCurrentWirelessNetwork(out var currentNetwork);
foreach (var network in adapter.NetworkReport.AvailableNetworks.FilterAndOrder())
{
@ -320,8 +347,8 @@ namespace SafeExamBrowser.SystemComponents.Network
}
}
Type = HasWirelessAdapter ? ConnectionType.Wireless : (hasInternet ? ConnectionType.Wired : ConnectionType.Undefined);
Status = hasInternet ? ConnectionStatus.Connected : (HasWirelessAdapter && isConnecting ? ConnectionStatus.Connecting : ConnectionStatus.Disconnected);
Type = HasWirelessAdapter ? ConnectionType.Wireless : (hasConnection ? ConnectionType.Wired : ConnectionType.Undefined);
Status = hasConnection ? ConnectionStatus.Connected : (isConnecting ? ConnectionStatus.Connecting : ConnectionStatus.Disconnected);
LogNetworkChanges(previousStatus, wirelessNetworks.FirstOrDefault(n => n.Status == ConnectionStatus.Connected));
}