Skip to content

Commit

Permalink
Add CanExtendByRewardedAdThreshold property
Browse files Browse the repository at this point in the history
  • Loading branch information
trudyhood committed Nov 29, 2024
1 parent fbb45a3 commit 82d2eac
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 16 deletions.
1 change: 1 addition & 0 deletions Tests/VpnHood.Test/TestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ public static AppOptions CreateAppOptions()
ServerQueryTimeout = TimeSpan.FromSeconds(2),
AutoDiagnose = false,
SingleLineConsoleLog = false,
CanExtendByRewardedAdThreshold = TimeSpan.Zero,
AdOptions = new AppAdOptions {
ShowAdPostDelay = TimeSpan.Zero,
LoadAdPostDelay = TimeSpan.Zero
Expand Down
6 changes: 5 additions & 1 deletion Tests/VpnHood.Test/Tests/AdTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ public async Task RewardedAd_expiration_must_be_increased_by_user(bool acceptAd)
var appOptions = TestHelper.CreateAppOptions();
var adProviderItem = new AppAdProviderItem { AdProvider = new TestAdProvider(accessManager) };
appOptions.AdProviderItems = [adProviderItem];
await using var app = TestHelper.CreateClientApp(appOptions: appOptions);
var device = new TestDevice(() => new NullPacketCapture { CanDetectInProcessPacket = true });
await using var app = TestHelper.CreateClientApp(appOptions: appOptions, device: device);

// create access token
var token = accessManager.CreateToken();
token.IsPublic = true;

// connect
var clientProfile = app.ClientProfileService.ImportAccessKey(token.ToAccessKey());
Expand Down Expand Up @@ -161,6 +163,7 @@ public async Task RewardedAd_should_toggle_by_canDetectInProcessPacket(bool canD

// create token
var token = accessManager.CreateToken();
token.IsPublic = true;

// connect
var clientProfile = app.ClientProfileService.ImportAccessKey(token.ToAccessKey());
Expand Down Expand Up @@ -190,6 +193,7 @@ public async Task RewardedAd_should_toggle_by_access_manager(bool enable)

// create token
var token = accessManager.CreateToken();
token.IsPublic = true;

// connect
var clientProfile = app.ClientProfileService.ImportAccessKey(token.ToAccessKey());
Expand Down
1 change: 1 addition & 0 deletions VpnHood.Client.App/AppOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ public static string BuildStorageFolderPath(string appId) =>
public bool AllowEndPointTracker { get; set; }
public string? DeviceId { get; set; }
public string? LocalSpaHostName { get; set; }
public TimeSpan CanExtendByRewardedAdThreshold { get; set; } = TimeSpan.FromMinutes(5);
}
18 changes: 12 additions & 6 deletions VpnHood.Client.App/VpnHoodApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class VpnHoodApp : Singleton<VpnHoodApp>,
private readonly bool _autoDiagnose;
private readonly AppAdService _appAppAdService;
private readonly bool _allowEndPointTracker;
private readonly TimeSpan _canExtendByRewardedAdThreshold;
private SessionStatus? LastSessionStatus => _client?.SessionStatus ?? _lastSessionStatus;
private string VersionCheckFilePath => Path.Combine(StorageFolderPath, "version.json");
public string TempFolderPath => Path.Combine(StorageFolderPath, "Temp");
Expand Down Expand Up @@ -117,6 +118,7 @@ private VpnHoodApp(IDevice device, AppOptions options)
_serverQueryTimeout = options.ServerQueryTimeout;
_appAppAdService = new AppAdService(this, options.AdProviderItems, options.AdOptions);
_allowEndPointTracker = options.AllowEndPointTracker;
_canExtendByRewardedAdThreshold = options.CanExtendByRewardedAdThreshold;
Diagnoser.StateChanged += (_, _) => FireConnectionStateChanged();
LogService = new AppLogService(Path.Combine(StorageFolderPath, FileNameLog), options.SingleLineConsoleLog);
ClientProfileService = new ClientProfileService(Path.Combine(StorageFolderPath, FolderNameProfiles));
Expand Down Expand Up @@ -147,7 +149,7 @@ private VpnHoodApp(IDevice device, AppOptions options)
var builtInProfileIds = ClientProfileService.ImportBuiltInAccessKeys(options.AccessKeys);

// remove default client profile if not exists
if (Settings.UserSettings.ClientProfileId!=null && ClientProfileService.FindById(Settings.UserSettings.ClientProfileId.Value)==null)
if (Settings.UserSettings.ClientProfileId != null && ClientProfileService.FindById(Settings.UserSettings.ClientProfileId.Value) == null)
Settings.UserSettings.ClientProfileId = null;

// set first built in profile as default if default is not set
Expand Down Expand Up @@ -397,11 +399,11 @@ public async Task Connect(
using var lockAsync = await _connectLock.LockAsync(cancellationToken);

// set use default clientProfile and serverLocation
clientProfileId ??= UserSettings.ClientProfileId ?? throw new NotExistsException("ClientProfile is not set.");
clientProfileId ??= UserSettings.ClientProfileId ?? throw new NotExistsException("ClientProfile is not set.");
var clientProfile = ClientProfileService.Get(clientProfileId.Value);
var clientProfileInfo = ClientProfileService.GetInfo(clientProfileId.Value);
var clientProfileInfo = ClientProfileService.GetInfo(clientProfileId.Value);
serverLocation ??= clientProfileInfo.SelectedLocationInfo?.ServerLocation;

// protect double call
if (!IsIdle) {
if (_activeClientProfileId == clientProfileId &&
Expand Down Expand Up @@ -571,7 +573,8 @@ private async Task ConnectInternal(Token token, string? serverLocation, string?
ForceLogSni = LogService.LogEvents.Contains(nameof(GeneralEventId.Sni), StringComparer.OrdinalIgnoreCase),
AllowAnonymousTracker = UserSettings.AllowAnonymousTracker,
AllowEndPointTracker = UserSettings.AllowAnonymousTracker && _allowEndPointTracker,
Tracker = Services.Tracker
Tracker = Services.Tracker,
CanExtendByRewardedAdThreshold = _canExtendByRewardedAdThreshold
};

if (_socketFactory != null) clientOptions.SocketFactory = _socketFactory;
Expand Down Expand Up @@ -925,9 +928,12 @@ await File.WriteAllTextAsync(VersionCheckFilePath, JsonSerializer.Serialize(_ver

public Task ExtendByRewardedAd(CancellationToken cancellationToken)
{
if (_client?.State!=ClientState.Connected)
if (_client?.State != ClientState.Connected)
throw new InvalidOperationException("Could not show ad. The VPN is not connected.");

if (State.SessionStatus?.AccessUsage?.CanExtendPremiumByRewardedAd != true)
throw new InvalidOperationException("Can not extend session by a rewarded ad at this time.");

return _client.ShowAd(true, cancellationToken);
}

Expand Down
2 changes: 1 addition & 1 deletion VpnHood.Client.Device.WinDivert/WinDivertPacketCapture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public bool AddIpV6Address {
public bool CanDetectInProcessPacket => false;
public bool IsInProcessPacket(ProtocolType protocol, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint)
{
throw new NotSupportedException();
throw new NotSupportedException("This device can not detect IsInProcessPacket.");
}

public WinDivertPacketCapture()
Expand Down
4 changes: 2 additions & 2 deletions VpnHood.Client.Device/NullPacketCapture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public virtual void SendPacketToOutbound(IList<IPPacket> ipPackets)

public bool IsInProcessPacket(ProtocolType protocol, IPEndPoint localEndPoint, IPEndPoint remoteEndPoint)
{
if (!IsAddIpV6AddressSupported)
throw new NotSupportedException("InProcessPacket is not supported");
if (!CanDetectInProcessPacket)
throw new NotSupportedException("This device can not detect IsInProcessPacket.");

return false;
}
Expand Down
1 change: 1 addition & 0 deletions VpnHood.Client/ClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public class ClientOptions
public bool ForceLogSni { get; set; }
public TimeSpan ServerQueryTimeout { get; set; } = TimeSpan.FromSeconds(10);
public ITracker? Tracker { get; set; }
public TimeSpan CanExtendByRewardedAdThreshold { get; set; } = TimeSpan.FromMinutes(5);

// ReSharper disable StringLiteralTypo
public const string SampleAccessKey =
Expand Down
33 changes: 27 additions & 6 deletions VpnHood.Client/VpnHoodClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public class VpnHoodClient : IAsyncDisposable
private DateTime? _autoWaitTime;
private readonly ServerFinder _serverFinder;
private readonly ConnectPlanId _planId;
private SessionStatus _sessionStatus = new();
private readonly TimeSpan _canExtendByRewardedAdThreshold;

private ConnectorService ConnectorService => VhUtil.GetRequiredInstance(_connectorService);
internal Nat Nat { get; }
internal Tunnel Tunnel { get; }
Expand All @@ -80,7 +83,6 @@ public class VpnHoodClient : IAsyncDisposable
public Token Token { get; }
public string ClientId { get; }
public ulong SessionId { get; private set; }
public SessionStatus SessionStatus { get; private set; } = new();
public Version Version { get; }
public bool IncludeLocalNetwork { get; }
public IpRangeOrderedList IncludeIpRanges { get; private set; } = new(IpNetwork.All.ToIpRanges());
Expand Down Expand Up @@ -127,6 +129,7 @@ public VpnHoodClient(IPacketCapture packetCapture, string clientId, Token token,
_useUdpChannel = options.UseUdpChannel;
_adService = options.AdService;
_planId = options.PlanId;
_canExtendByRewardedAdThreshold = options.CanExtendByRewardedAdThreshold;
_serverFinder = new ServerFinder(options.SocketFactory, token.ServerToken,
serverLocation: options.ServerLocation,
serverQueryTimeout: options.ServerQueryTimeout,
Expand Down Expand Up @@ -164,6 +167,15 @@ public VpnHoodClient(IPacketCapture packetCapture, string clientId, Token token,
Stat = new ClientStat(this);
}

public SessionStatus SessionStatus {
get {
if (_sessionStatus.AccessUsage != null)
_sessionStatus.AccessUsage.CanExtendPremiumByRewardedAd = CanExtendByRewardedAd(_sessionStatus.AccessUsage);
return _sessionStatus;
}
}


public IPAddress[] DnsServers {
get => _dnsServers;
private set {
Expand All @@ -188,6 +200,15 @@ private set {
}
}

private bool CanExtendByRewardedAd(AccessUsage accessUsage)
{
return accessUsage is { CanExtendPremiumByRewardedAd: true, ExpirationTime: not null } &&
accessUsage.ExpirationTime > FastDateTime.UtcNow + _canExtendByRewardedAdThreshold &&
_packetCapture.CanDetectInProcessPacket &&
_adService is { CanShowRewarded: true } &&
Token.IsPublic;
}

public bool UseUdpChannel {
get => _useUdpChannel;
set {
Expand Down Expand Up @@ -263,7 +284,7 @@ public async Task Connect(CancellationToken cancellationToken = default)

// Starting
State = ClientState.Connecting;
SessionStatus = new SessionStatus();
_sessionStatus = new SessionStatus();

// Connect
try {
Expand Down Expand Up @@ -863,9 +884,8 @@ internal async Task<ConnectorRequestResult<T>> SendRequest<T>(ClientRequest requ
// create a connection and send the request
var requestResult = await ConnectorService.SendRequest<T>(request, cancellationToken).VhConfigureAwait();
if (requestResult.Response.AccessUsage != null)
requestResult.Response.AccessUsage.CanExtendPremiumByRewardedAd &=
_packetCapture.CanDetectInProcessPacket && _adService is { CanShowRewarded: true };

requestResult.Response.AccessUsage.CanExtendPremiumByRewardedAd = CanExtendByRewardedAd(requestResult.Response.AccessUsage);

// set SessionStatus
if (requestResult.Response.AccessUsage != null)
SessionStatus.AccessUsage = requestResult.Response.AccessUsage;
Expand Down Expand Up @@ -969,7 +989,7 @@ private async Task SendByeRequest(CancellationToken cancellationToken)

_isWaitingForAd = true;
_clientHost.PassthruInProcessPackets = true;
var adResult = rewarded
var adResult = rewarded
? await _adService.ShowRewarded(ActiveUiContext.RequiredContext, SessionId.ToString(), cancellationToken).VhConfigureAwait()
: await _adService.ShowInterstitial(ActiveUiContext.RequiredContext, SessionId.ToString(), cancellationToken).VhConfigureAwait();

Expand Down Expand Up @@ -1051,6 +1071,7 @@ public ValueTask DisposeAsync()
}

private readonly AsyncLock _disposeLock = new();

public async ValueTask DisposeAsync(bool waitForBye)
{
using var lockResult = await _disposeLock.LockAsync(TimeSpan.Zero).VhConfigureAwait();
Expand Down

0 comments on commit 82d2eac

Please sign in to comment.