Skip to content

Commit

Permalink
Handle IPC controller exceptions; Use ConcurrentHashSet for AppSettin…
Browse files Browse the repository at this point in the history
…gs [VPNWIN-1464][VPNWIN-1470]
  • Loading branch information
eaproton committed Apr 19, 2023
1 parent c3884e6 commit 740e117
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,25 @@ private async Task CreateInternalAsync()
int? appServerPort = _grpcServer?.Port;
if (VpnController is not null && appServerPort is not null)
{
Logger.Info<ProcessCommunicationLog>($"Sending app gRPC server port {appServerPort.Value} to service.");
await RegisterStateConsumerAsync(appServerPort.Value);
}
}

private async Task RegisterStateConsumerAsync(int appServerPort)
{
Logger.Info<ProcessCommunicationLog>($"Sending the app gRPC server port {appServerPort} to service.");
try
{
await VpnController.RegisterStateConsumer(new StateConsumerIpcEntity
{
ServerPort = appServerPort.Value
ServerPort = appServerPort
});
}
catch (Exception e)
{
Logger.Error<ProcessCommunicationErrorLog>($"An error occurred when " +
$"sending the app gRPC server port {appServerPort} to service.", e);
}
}

public async Task RecreateAsync()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
Expand Down Expand Up @@ -32,11 +32,33 @@ public static async Task OpenMainWindowAsync()
int? appServerPort = appServerPortRegister.ReadOnce();
if (appServerPort.HasValue && GrpcChannelWrapperFactory.IsPortValid(appServerPort.Value))
{
GrpcChannelWrapper grpcChannelWrapper = new(appServerPort.Value);
await CreateGrpcChannelAndSendOpenWindowCommandAsync(appServerPort.Value);
}
}

private static async Task CreateGrpcChannelAndSendOpenWindowCommandAsync(int appServerPort)
{
try
{
GrpcChannelWrapper grpcChannelWrapper = new(appServerPort);
IAppController appController = grpcChannelWrapper.CreateService<IAppController>();
await appController.OpenWindow();
await SendOpenWindowCommandAsync(appController);
await grpcChannelWrapper.ShutdownAsync();
}
catch
{
}
}

private static async Task SendOpenWindowCommandAsync(IAppController appController)
{
try
{
await appController.OpenWindow();
}
catch
{
}
}
}
}
9 changes: 5 additions & 4 deletions src/ProtonVPN.App/Core/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using ProtonVPN.Announcements.Contracts;
using ProtonVPN.Api.Contracts.ReportAnIssue;
using ProtonVPN.Common;
using ProtonVPN.Common.Collections.Concurrent;
using ProtonVPN.Common.Configuration;
using ProtonVPN.Common.Extensions;
using ProtonVPN.Common.KillSwitch;
Expand All @@ -53,7 +54,7 @@ internal class AppSettings : IAppSettings, INotifyPropertyChanged, ILoggedInAwar
private readonly ISettingsStorage _storage;
private readonly UserSettings _userSettings;
private readonly IConfiguration _config;
private readonly HashSet<string> _accessedPerUserProperties = new();
private readonly ConcurrentHashSet<string> _accessedPerUserProperties = new();

public AppSettings(ILogger logger,
ISettingsStorage storage,
Expand Down Expand Up @@ -695,21 +696,21 @@ private void LogChange<T>(string propertyName, T oldValue, T newValue)

private T GetPerUser<T>([CallerMemberName] string propertyName = null)
{
_accessedPerUserProperties.Add(propertyName);
_accessedPerUserProperties.TryAdd(propertyName);

return _userSettings.Get<T>(propertyName);
}

private string GetPerUserDecrypted([CallerMemberName] string propertyName = null)
{
_accessedPerUserProperties.Add(propertyName);
_accessedPerUserProperties.TryAdd(propertyName);

return _userSettings.Get<string>(propertyName)?.Decrypt();
}

private void SetPerUserInner<T>(T value, string propertyName)
{
_accessedPerUserProperties.Add(propertyName);
_accessedPerUserProperties.TryAdd(propertyName);

T oldValue = default;
Type toType = UnwrapNullable(typeof(T));
Expand Down
8 changes: 5 additions & 3 deletions src/ProtonVPN.App/Core/Service/ServiceControllerCaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ProtonVPN.Common.Abstract;
using ProtonVPN.Common.Extensions;
using ProtonVPN.Common.Logging;
using ProtonVPN.Common.Logging.Categorization.Events.AppServiceLogs;
using ProtonVPN.ProcessCommunication.Contracts;
Expand All @@ -40,7 +42,7 @@ protected ServiceControllerCaller(ILogger logger, IAppGrpcClient grpcClient, Vpn
_vpnSystemService = vpnSystemService;
}

protected async Task<T> Invoke<T>(Func<Controller, Task<T>> serviceCall,
protected async Task<Result<T>> Invoke<T>(Func<Controller, Task<T>> serviceCall,
[CallerMemberName] string memberName = "")
{
int retryCount = 5;
Expand All @@ -56,15 +58,15 @@ protected async Task<T> Invoke<T>(Func<Controller, Task<T>> serviceCall,
await task;
}

return result;
return Result.Ok(result);
}
catch (Exception e)
{
await StartServiceIfStoppedAsync();
if (retryCount <= 0)
{
LogError(e, memberName, isToRetry: false);
throw;
return Result.Fail<T>(e.CombinedMessage());
}

await _grpcClient.RecreateAsync();
Expand Down
4 changes: 2 additions & 2 deletions src/ProtonVPN.App/Core/Service/Update/UpdateServiceCaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ namespace ProtonVPN.Core.Service.Update
{
public class UpdateServiceCaller : ServiceControllerCaller<IUpdateController>
{
public UpdateServiceCaller(ILogger logger, IAppGrpcClient grpcClient, VpnSystemService vpnSystemService) : base(
logger, grpcClient, vpnSystemService)
public UpdateServiceCaller(ILogger logger, IAppGrpcClient grpcClient, VpnSystemService vpnSystemService)
: base(logger, grpcClient, vpnSystemService)
{
}

Expand Down
13 changes: 1 addition & 12 deletions src/ProtonVPN.App/Core/Service/Vpn/VpnConnectionSpeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,7 @@ private async void UpdateSpeed(object sender, EventArgs e)
InOutBytes total;
using (await _lock.Lock())
{
try
{
total = await _vpnServiceManager.Total();
}
catch (CommunicationException)
{
return;
}
catch (TimeoutException)
{
return;
}
total = await _vpnServiceManager.GetTrafficBytes();
}

_speed = total - _total;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ await InvokeAction(async () =>
});
}

public async Task<InOutBytes> Total()
public async Task<InOutBytes> GetTrafficBytes()
{
return await _decorated.Total();
return await _decorated.GetTrafficBytes();
}

public async Task RepeatState()
Expand Down
8 changes: 4 additions & 4 deletions src/ProtonVPN.App/Core/Service/Vpn/VpnServiceCaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

using System.Threading.Tasks;
using ProtonVPN.Common.Abstract;
using ProtonVPN.Common.Extensions;
using ProtonVPN.Common.Logging;
using ProtonVPN.ProcessCommunication.Contracts;
Expand All @@ -31,8 +32,8 @@ namespace ProtonVPN.Core.Service.Vpn
{
public class VpnServiceCaller : ServiceControllerCaller<IVpnController>
{
public VpnServiceCaller(ILogger logger, IAppGrpcClient grpcClient, VpnSystemService vpnSystemService) : base(
logger, grpcClient, vpnSystemService)
public VpnServiceCaller(ILogger logger, IAppGrpcClient grpcClient, VpnSystemService vpnSystemService)
: base(logger, grpcClient, vpnSystemService)
{
}

Expand Down Expand Up @@ -61,7 +62,7 @@ public Task RepeatState()
return Invoke(c => c.RepeatState().Wrap());
}

public Task<TrafficBytesIpcEntity> Total()
public Task<Result<TrafficBytesIpcEntity>> GetTrafficBytes()
{
return Invoke(c => c.GetTrafficBytes());
}
Expand All @@ -71,7 +72,6 @@ public Task RequestNetShieldStats()
return Invoke(c => c.RequestNetShieldStats().Wrap());
}


public Task RegisterVpnClient(int port)
{
return Invoke(c => c.RegisterStateConsumer(new StateConsumerIpcEntity { ServerPort = port }).Wrap());
Expand Down
9 changes: 6 additions & 3 deletions src/ProtonVPN.App/Core/Service/Vpn/VpnServiceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using ProtonVPN.Common.Abstract;
using ProtonVPN.Common.Helpers;
using ProtonVPN.Common.Logging;
using ProtonVPN.Common.Logging.Categorization.Events.DisconnectLogs;
Expand Down Expand Up @@ -118,9 +118,12 @@ public async Task UpdateAuthCertificate(string certificate)
await _vpnServiceCaller.UpdateAuthCertificate(new AuthCertificateIpcEntity() { Certificate = certificate });
}

public async Task<InOutBytes> Total()
public async Task<InOutBytes> GetTrafficBytes()
{
return _entityMapper.Map<TrafficBytesIpcEntity, InOutBytes>(await _vpnServiceCaller.Total());
Result<TrafficBytesIpcEntity> trafficBytes = await _vpnServiceCaller.GetTrafficBytes();
return trafficBytes.Success
? _entityMapper.Map<TrafficBytesIpcEntity, InOutBytes>(trafficBytes.Value)
: InOutBytes.Zero;
}

public async Task RepeatState()
Expand Down
2 changes: 1 addition & 1 deletion src/ProtonVPN.App/Windows/IOpenMainWindowAware.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
Expand Down
45 changes: 45 additions & 0 deletions src/ProtonVPN.Common/Collections/Concurrent/ConcurrentHashSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
* ProtonVPN is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProtonVPN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
*/

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace ProtonVPN.Common.Collections.Concurrent
{
public class ConcurrentHashSet<T>
{
private readonly ConcurrentDictionary<T, bool> _dictionary = new();

public bool TryAdd(T item)
{
return _dictionary.TryAdd(item, true);
}

public List<T> ToList()
{
return _dictionary.Keys.ToList();
}

public void Clear()
{
_dictionary.Clear();
}
}
}
2 changes: 1 addition & 1 deletion src/ProtonVPN.Common/Logging/NullLogger.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Proton Technologies AG
* Copyright (c) 2023 Proton AG
*
* This file is part of ProtonVPN.
*
Expand Down
2 changes: 1 addition & 1 deletion src/ProtonVPN.Core/Vpn/IVpnServiceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Task Disconnect(VpnError vpnError,
[CallerFilePath] string sourceFilePath = "",
[CallerMemberName] string sourceMemberName = "",
[CallerLineNumber] int sourceLineNumber = 0);
Task<InOutBytes> Total();
Task<InOutBytes> GetTrafficBytes();
Task RepeatState();

void RegisterVpnStateCallback(Action<VpnStateChangedEventArgs> callback);
Expand Down

0 comments on commit 740e117

Please sign in to comment.