Skip to content

Commit 5b177e3

Browse files
[feature] Add protocol version validation for member and joiner (#248)
1 parent bdfd2cb commit 5b177e3

File tree

26 files changed

+1332
-23
lines changed

26 files changed

+1332
-23
lines changed

src/ByteSync.Client/Business/Communications/PublicKeysTrusting/JoinerTrustProcessData.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public JoinerTrustProcessData()
1313

1414
NonStoredPublicKeyCheckDatas = new List<PublicKeyCheckData>();
1515
FullyTrustedPublicKeyCheckDatas = new List<PublicKeyCheckData>();
16+
IncompatibleMemberClientInstanceIds = new List<string>();
1617
}
1718

1819
private List<string>? ExpectedPublicKeyCheckDataMembers { get; set; }
@@ -22,6 +23,10 @@ public JoinerTrustProcessData()
2223
public List<PublicKeyCheckData> NonStoredPublicKeyCheckDatas { get; }
2324

2425
public List<PublicKeyCheckData> FullyTrustedPublicKeyCheckDatas { get; }
26+
27+
public List<string> IncompatibleMemberClientInstanceIds { get; }
28+
29+
public bool IsProtocolVersionIncompatible => IncompatibleMemberClientInstanceIds.Count > 0;
2530

2631
private PublicKeyCheckData?[] ReceivedMembersPublicKeyCheckDatas { get; set; }
2732

@@ -91,4 +96,14 @@ public ReadOnlyCollection<PublicKeyCheckData> GetReceivedPublicKeyCheckData()
9196
.ToList()
9297
.AsReadOnly();
9398
}
99+
100+
public void SetProtocolVersionIncompatible(string memberClientInstanceId)
101+
{
102+
if (!IncompatibleMemberClientInstanceIds.Contains(memberClientInstanceId))
103+
{
104+
IncompatibleMemberClientInstanceIds.Add(memberClientInstanceId);
105+
}
106+
107+
WaitForAllPublicKeyCheckDatasReceived.Set();
108+
}
94109
}

src/ByteSync.Client/Interfaces/Controls/Communications/Http/ITrustApiClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@ public interface ITrustApiClient
1818
Task SendDigitalSignatures(SendDigitalSignaturesParameters parameters, CancellationToken cancellationToken = default);
1919

2020
Task SetAuthChecked(SetAuthCheckedParameters parameters, CancellationToken cancellationToken = default);
21+
22+
Task InformProtocolVersionIncompatible(InformProtocolVersionIncompatibleParameters parameters, CancellationToken cancellationToken = default);
2123
}

src/ByteSync.Client/Interfaces/Controls/Communications/ITrustProcessPublicKeysRepository.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,8 @@ public interface ITrustProcessPublicKeysRepository : IRepository<TrustProcessPub
2828
Task<PublicKeyCheckData?> GetLocalPublicKeyCheckData(string sessionId, string joinerClientInstanceId);
2929

3030
Task SetOtherPartyChecked(string sessionId, PublicKeyValidationParameters publicKeyValidationParameters);
31+
32+
Task SetProtocolVersionIncompatible(string sessionId, string memberClientInstanceId);
33+
34+
Task<bool> IsProtocolVersionIncompatible(string sessionId);
3135
}

src/ByteSync.Client/Interfaces/Controls/Communications/SignalR/IHubPushHandler2.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ public interface IHubPushHandler2
4242
Subject<(string, LobbyCheckInfo)> LobbyCheckInfosSent { get; }
4343
Subject<(string, string, LobbyMemberStatuses)> LobbyMemberStatusUpdated { get; }
4444
Subject<LobbyCloudSessionCredentials> LobbyCloudSessionCredentialsSent { get; }
45+
Subject<InformProtocolVersionIncompatibleParameters> InformProtocolVersionIncompatible { get; }
4546
}

src/ByteSync.Client/Services/Communications/Api/TrustApiClient.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@ public async Task SetAuthChecked(SetAuthCheckedParameters parameters, Cancellati
102102
}
103103
}
104104

105+
public async Task InformProtocolVersionIncompatible(InformProtocolVersionIncompatibleParameters parameters, CancellationToken cancellationToken = default)
106+
{
107+
try
108+
{
109+
await _apiInvoker.PostAsync($"trust/informProtocolVersionIncompatible", parameters, cancellationToken);
110+
}
111+
catch (Exception ex)
112+
{
113+
LogError(ex);
114+
115+
throw;
116+
}
117+
}
118+
105119
private void LogError(Exception exception, [CallerMemberName] string caller = "")
106120
{
107121
// ReSharper disable once TemplateIsNotCompileTimeConstantProblem

src/ByteSync.Client/Services/Communications/PublicKeysTruster.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ public async Task<JoinSessionResult> TrustAllMembersPublicKeys(string sessionId,
7474
// Called during StartTrustCheck on the session members so that they provide their PublicKeyCheckData to the joiner
7575
public async Task OnPublicKeyCheckDataAskedAsync((string sessionId, string clientInstanceId, PublicKeyInfo publicKeyInfo) tuple)
7676
{
77+
// Validate protocol version compatibility before responding
78+
if (!ProtocolVersion.IsCompatible(tuple.publicKeyInfo.ProtocolVersion))
79+
{
80+
_logger.LogWarning(
81+
"Protocol version mismatch in OnPublicKeyCheckDataAskedAsync: joiner has version {JoinerVersion}, current version is {CurrentVersion}. Not responding to trust check request.",
82+
tuple.publicKeyInfo.ProtocolVersion, ProtocolVersion.CURRENT);
83+
84+
var incompatibleParameters = new InformProtocolVersionIncompatibleParameters
85+
{
86+
SessionId = tuple.sessionId,
87+
MemberClientInstanceId = _environmentService.ClientInstanceId,
88+
JoinerClientInstanceId = tuple.clientInstanceId,
89+
MemberProtocolVersion = ProtocolVersion.CURRENT,
90+
JoinerProtocolVersion = tuple.publicKeyInfo.ProtocolVersion
91+
};
92+
93+
await _trustApiClient.InformProtocolVersionIncompatible(incompatibleParameters);
94+
95+
return;
96+
}
97+
7798
var isTrusted = _publicKeysManager.IsTrusted(tuple.publicKeyInfo);
7899

79100
var memberPublicKeyCheckData = _publicKeysManager.BuildMemberPublicKeyCheckData(tuple.publicKeyInfo, isTrusted);
@@ -272,6 +293,13 @@ private async Task<JoinSessionResult> InitiateAndWaitForTrustCheck(string sessio
272293

273294
if (result == null || !result.IsOK)
274295
{
296+
if (result is { IsProtocolVersionIncompatible: true })
297+
{
298+
_logger.LogWarning("StartTrustCheck returned protocol version incompatibility");
299+
300+
return JoinSessionResult.BuildFrom(JoinSessionStatus.IncompatibleProtocolVersion);
301+
}
302+
275303
_logger.LogError("Can not start trust check");
276304

277305
return JoinSessionResult.BuildFrom(JoinSessionStatus.UnexpectedError);
@@ -285,6 +313,13 @@ private async Task<JoinSessionResult> InitiateAndWaitForTrustCheck(string sessio
285313

286314
if (isWaitOK)
287315
{
316+
if (await _trustProcessPublicKeysRepository.IsProtocolVersionIncompatible(sessionId))
317+
{
318+
_logger.LogWarning("Trust check interrupted due to protocol version incompatibility");
319+
320+
return JoinSessionResult.BuildFrom(JoinSessionStatus.IncompatibleProtocolVersion);
321+
}
322+
288323
return JoinSessionResult.BuildProcessingNormally();
289324
}
290325
else

src/ByteSync.Client/Services/Communications/PushReceivers/PublicKeyCheckDataPushReceiver.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public PublicKeyCheckDataPushReceiver(IHubPushHandler2 hubPushHandler2, IPublicK
2929
_hubPushHandler2.RequestTrustPublicKey.Subscribe(OnTrustPublicKeyRequested);
3030
_hubPushHandler2.InformPublicKeyValidationIsFinished.Subscribe(OnPublicKeyValidationIsFinished);
3131
_hubPushHandler2.RequestCheckDigitalSignature.Subscribe(OnRequestCheckDigitalSignature);
32+
_hubPushHandler2.InformProtocolVersionIncompatible.Subscribe(OnProtocolVersionIncompatible);
3233
}
3334

3435
private async void OnPublicKeyCheckDataAsked((string sessionId, string clientInstanceId, PublicKeyInfo publicKeyInfo) tuple)
@@ -91,4 +92,16 @@ private async void OnRequestCheckDigitalSignature(DigitalSignatureCheckInfo digi
9192
_logger.LogError(ex, "OnRequestCheckDigitalSignature");
9293
}
9394
}
95+
96+
private async void OnProtocolVersionIncompatible(InformProtocolVersionIncompatibleParameters parameters)
97+
{
98+
try
99+
{
100+
await _trustProcessPublicKeysRepository.SetProtocolVersionIncompatible(parameters.SessionId, parameters.MemberClientInstanceId);
101+
}
102+
catch (Exception ex)
103+
{
104+
_logger.LogError(ex, "OnProtocolVersionIncompatible");
105+
}
106+
}
94107
}

src/ByteSync.Client/Services/Communications/SignalR/HubPushHandler2.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ public HubPushHandler2(IConnectionService connectionService, ILogger<HubPushHand
7171
new SubjectInfo<string, string>(nameof(IHubByteSyncPush.MemberQuittedLobby)),
7272
new SubjectInfo<string, LobbyCheckInfo>(nameof(IHubByteSyncPush.LobbyCheckInfosSent)),
7373
new SubjectInfo<string, string, LobbyMemberStatuses>(nameof(IHubByteSyncPush.LobbyMemberStatusUpdated)),
74-
new SubjectInfo<LobbyCloudSessionCredentials>(nameof(IHubByteSyncPush.LobbyCloudSessionCredentialsSent))
74+
new SubjectInfo<LobbyCloudSessionCredentials>(nameof(IHubByteSyncPush.LobbyCloudSessionCredentialsSent)),
75+
new SubjectInfo<InformProtocolVersionIncompatibleParameters>(nameof(IHubByteSyncPush.InformProtocolVersionIncompatible))
7576
];
7677

7778
public Subject<(CloudSessionResult, ValidateJoinCloudSessionParameters)> YouJoinedSession =>
@@ -166,6 +167,9 @@ public HubPushHandler2(IConnectionService connectionService, ILogger<HubPushHand
166167

167168
public Subject<LobbyCloudSessionCredentials> LobbyCloudSessionCredentialsSent =>
168169
GetSubject<LobbyCloudSessionCredentials>(nameof(IHubByteSyncPush.LobbyCloudSessionCredentialsSent));
170+
171+
public Subject<InformProtocolVersionIncompatibleParameters> InformProtocolVersionIncompatible =>
172+
GetSubject<InformProtocolVersionIncompatibleParameters>(nameof(IHubByteSyncPush.InformProtocolVersionIncompatible));
169173

170174
private async Task SetConnection(HubConnection connection)
171175
{

src/ByteSync.Client/Services/Communications/TrustProcessPublicKeysRepository.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ await RunAsync(sessionId, data =>
8585
});
8686
}
8787

88+
public async Task SetProtocolVersionIncompatible(string sessionId, string memberClientInstanceId)
89+
{
90+
await RunAsync(sessionId, data =>
91+
{
92+
data.JoinerTrustProcessData.SetProtocolVersionIncompatible(memberClientInstanceId);
93+
});
94+
}
95+
96+
public async Task<bool> IsProtocolVersionIncompatible(string sessionId)
97+
{
98+
return await GetAsync(sessionId, data => data.JoinerTrustProcessData.IsProtocolVersionIncompatible);
99+
}
100+
88101
protected override string GetDataId(TrustProcessPublicKeysData data)
89102
{
90103
return data.SessionId;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace ByteSync.Common.Business.Sessions.Cloud.Connections;
2+
3+
public class InformProtocolVersionIncompatibleParameters
4+
{
5+
public string SessionId { get; set; } = null!;
6+
7+
public string MemberClientInstanceId { get; set; } = null!;
8+
9+
public string JoinerClientInstanceId { get; set; } = null!;
10+
11+
public int MemberProtocolVersion { get; set; }
12+
13+
public int JoinerProtocolVersion { get; set; }
14+
}

0 commit comments

Comments
 (0)