Skip to content

Commit 6913da4

Browse files
committed
client console can now submit a did key, changed a bunch of unload s over
1 parent 73859da commit 6913da4

51 files changed

Lines changed: 521 additions & 124 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Basis Server/BasisNetworkClientConsole/BasisNetworkClientConsole/BasisNetworkClientConsole.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
<ItemGroup>
1414
<ProjectReference Include="..\..\BasisNetworkClient\BasisNetworkClient.csproj" />
1515
<ProjectReference Include="..\..\BasisNetworkCore\BasisNetworkCore.csproj" />
16+
<ProjectReference Include="..\..\Contrib\Auth\Did\Did.csproj" />
17+
<ProjectReference Include="..\..\Contrib\Crypto\Crypto.csproj" />
1618
<ProjectReference Include="..\..\LiteNetLib\LiteNetLib.csproj" />
1719
</ItemGroup>
1820
</Project>

Basis Server/BasisNetworkClientConsole/BasisNetworkClientConsole/ClientManager.cs

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
using Basis.Config;
2+
using Basis.Contrib.Auth.DecentralizedIds.Newtypes;
3+
using Basis.Contrib.Crypto;
24
using Basis.Network.Core;
35
using Basis.Network.Core.Compression;
46
using Basis.Scripts.BasisSdk.Players;
57
using Basis.Utilities;
8+
using BasisNetworkClient;
69
using System.Text;
710
using System.Threading;
811
using static Basis.Network.Core.Compression.BasisAvatarBitPacking;
12+
using static Basis.Network.Core.Serializable.SerializableBasis;
913
using static SerializableBasis;
1014

1115
namespace Basis.Network
@@ -40,14 +44,14 @@ public async Task StartClientsAsync()
4044
for (int Index = 0; Index < ClientCount; Index++)
4145
{
4246
var name = NameGenerator.GenerateRandomPlayerName();
43-
var uuid = Guid.NewGuid().ToString();
47+
var identity = new ConsoleClientIdentity();
4448

4549
var readyMessage = new ReadyMessage
4650
{
4751
playerMetaDataMessage = new ClientMetaDataMessage
4852
{
4953
playerDisplayName = name,
50-
playerUUID = uuid,
54+
playerUUID = identity.Did,
5155
playerPlatform = "Headless",
5256
},
5357
clientAvatarChangeMessage = new ClientAvatarChangeMessage
@@ -71,13 +75,13 @@ public async Task StartClientsAsync()
7175

7276
if (peer != null)
7377
{
74-
netClient.listener.NetworkReceiveEvent += MessageHandler.OnReceive;
78+
netClient.listener.NetworkReceiveEvent += (p, r, ch, m) => MessageHandler.OnReceive(identity, p, r, ch, m);
7579
netClient.listener.PeerDisconnectedEvent += MessageHandler.OnDisconnect;
7680

7781
lock (clients) clients.Add(netClient);
7882
lock (peers) peers.Add(peer);
7983

80-
BNL.Log($"Connected: {name} ({uuid})");
84+
BNL.Log($"Connected: {name} ({identity.Did})");
8185
}
8286

8387
await Task.Delay(1, cts.Token);
@@ -91,20 +95,24 @@ public async Task ReconnectClientAsync(int index)
9195

9296
var oldClient = clients[index];
9397

98+
if (oldClient?.listener != null)
99+
{
100+
oldClient.listener.PeerDisconnectedEvent -= MessageHandler.OnDisconnect;
101+
}
94102
oldClient?.Disconnect();
95103
BNL.Log($"Disconnected client at index {index}");
96104

97105
await Task.Delay(3000); // wait before reconnecting
98106

99107
var name = NameGenerator.GenerateRandomPlayerName();
100-
var uuid = Guid.NewGuid().ToString();
108+
var identity = new ConsoleClientIdentity();
101109

102110
var readyMessage = new ReadyMessage
103111
{
104112
playerMetaDataMessage = new ClientMetaDataMessage
105113
{
106114
playerDisplayName = name,
107-
playerUUID = uuid,
115+
playerUUID = identity.Did,
108116
playerPlatform = "Headless",
109117
},
110118
clientAvatarChangeMessage = new ClientAvatarChangeMessage
@@ -127,14 +135,14 @@ public async Task ReconnectClientAsync(int index)
127135

128136
if (peer != null)
129137
{
130-
netClient.listener.NetworkReceiveEvent += MessageHandler.OnReceive;
138+
netClient.listener.NetworkReceiveEvent += (p, r, ch, m) => MessageHandler.OnReceive(identity, p, r, ch, m);
131139
netClient.listener.PeerDisconnectedEvent += MessageHandler.OnDisconnect;
132140

133141
lock (clients) clients[index] = netClient;
134142
Interlocked.Exchange(ref FinalClients[index], netClient);
135143
Interlocked.Exchange(ref FinalPeers[index], peer);
136144

137-
BNL.Log($"Reconnected: {name} ({uuid}) at index {index}");
145+
BNL.Log($"Reconnected: {name} ({identity.Did}) at index {index}");
138146
}
139147
}
140148
public Task StopClientsAsync()
@@ -147,10 +155,47 @@ public Configuration CreateConfig()
147155
Configuration Configuration = new Configuration();
148156
Basis.Network.Core.BasisTransportConfigStore.Get<Basis.Network.Core.LNLTransportConfig>(
149157
Basis.Network.Core.BasisNetworkStackRegistry.LiteNetLibId).UseNativeSockets = true;
150-
///we dont use auth identity as we are fake client system
151-
Configuration.UseAuthIdentity = false;
158+
Configuration.UseAuthIdentity = true;
152159

153160
return Configuration;
154161
}
155162
}
163+
164+
public sealed class ConsoleClientIdentity
165+
{
166+
private readonly PrivKey _privateKey;
167+
168+
public string Did { get; }
169+
170+
public ConsoleClientIdentity()
171+
{
172+
BasisDIDAuthIdentityClient.ClientKeyCreation(out (PubKey, PrivKey) keys, out Did did);
173+
_privateKey = keys.Item2;
174+
Did = did.V;
175+
}
176+
177+
public bool TryRespondToChallenge(NetPacketReader reader, out NetDataWriter writer)
178+
{
179+
writer = new NetDataWriter();
180+
181+
BytesMessage challenge = new BytesMessage();
182+
if (!challenge.Deserialize(reader, out byte[] nonce))
183+
{
184+
BNL.LogError("Malformed auth challenge from server");
185+
return false;
186+
}
187+
188+
if (!Ed25519.Sign(_privateKey, new Payload(nonce), out Signature? signature) || signature == null)
189+
{
190+
BNL.LogError("Unable to sign auth challenge");
191+
return false;
192+
}
193+
194+
BytesMessage signatureBytes = new BytesMessage();
195+
BytesMessage fragmentBytes = new BytesMessage();
196+
signatureBytes.Serialize(writer, signature.V);
197+
fragmentBytes.Serialize(writer, Encoding.UTF8.GetBytes("N/A"));
198+
return true;
199+
}
200+
}
156201
}

Basis Server/BasisNetworkClientConsole/BasisNetworkClientConsole/MessageHandler.cs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Basis.Network.Core;
2-
using BasisNetworkClient;
32
using static SerializableBasis;
43

54
namespace Basis.Network
@@ -11,14 +10,14 @@ public static void OnDisconnect(NetPeer peer, DisconnectInfo info)
1110
BNL.LogError($"Peer {peer.Id} disconnected.");
1211
}
1312

14-
public static void OnReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod method)
13+
public static void OnReceive(ConsoleClientIdentity identity, NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod method)
1514
{
1615
if (peer.Id != 0) return;
1716

1817
switch (channel)
1918
{
2019
case BasisNetworkCommons.AuthIdentityChannel:
21-
AuthIdentityMessage(peer, reader, channel);
20+
AuthIdentityMessage(identity, peer, reader);
2221
return; // already recycled inside
2322
case BasisNetworkCommons.metaDataChannel:
2423
break;
@@ -43,21 +42,17 @@ public static void OnReceive(NetPeer peer, NetPacketReader reader, byte channel,
4342
reader.Recycle();
4443
}
4544

46-
public static void AuthIdentityMessage(NetPeer peer, NetPacketReader Reader, byte channel)
45+
public static void AuthIdentityMessage(ConsoleClientIdentity identity, NetPeer peer, NetPacketReader reader)
4746
{
48-
BNL.Log("Validated Size " + Reader.AvailableBytes);
49-
if (BasisDIDAuthIdentityClient.IdentityMessage(peer, Reader, out NetDataWriter Writer))
47+
if (identity != null && identity.TryRespondToChallenge(reader, out NetDataWriter writer))
5048
{
51-
BNL.Log("Sent Identity To Server!");
52-
peer.Send(Writer, BasisNetworkCommons.AuthIdentityChannel, DeliveryMethod.ReliableOrdered);
53-
Reader.Recycle();
49+
peer.Send(writer, BasisNetworkCommons.AuthIdentityChannel, DeliveryMethod.ReliableOrdered);
5450
}
5551
else
5652
{
57-
BNL.LogError("Failed Identity Message!");
58-
Reader.Recycle();
53+
BNL.LogError("Failed to respond to auth challenge!");
5954
}
60-
BNL.Log("Completed");
55+
reader.Recycle();
6156
}
6257
}
6358
}

Basis Server/BasisNetworkCore/BasisConfigXmlDocs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private static void RegisterServerConfig()
165165
t.Fields.Add(new FieldDoc("IPv6Address", " IPv6 address to bind. ::1 = loopback, :: = all IPv6 interfaces. string. "));
166166
t.Fields.Add(new FieldDoc("Password", " Password clients must present to join. Change this for any non-local server! string. ", " ===== Authentication ===== "));
167167
t.Fields.Add(new FieldDoc("UseAuth", " Require the join password (above) to be correct. true|false. "));
168-
t.Fields.Add(new FieldDoc("UseAuthIdentity", " Require cryptographic player-identity (DID) verification in addition to the password. true|false. Headless/load-test fake clients require this to be false. "));
168+
t.Fields.Add(new FieldDoc("UseAuthIdentity", " Require cryptographic player-identity (DID) verification in addition to the password. true|false. The headless load-test client console supports this, so it can stay enabled. "));
169169
t.Fields.Add(new FieldDoc("NetworkStackId", " Transport stack id. Empty = the default ('litenetlib'); only 'litenetlib' is registered and unknown ids fall back to it. Per-stack tuning lives in config/transports/<id>.xml. string. "));
170170
t.Fields.Add(new FieldDoc("BasisUserRestrictionMode", " Player join restriction mode. Allowed values: Normal | BlackList | WhiteList. "));
171171
t.Fields.Add(new FieldDoc("HowManyDuplicateAuthCanExist", " How many connections sharing the same auth identity may exist at once. int. "));

Basis Server/BasisNetworkServer/BasisNetworkHandleErrorReport.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public static class BasisNetworkHandleErrorReport
3030
new ConcurrentDictionary<string, HashSet<string>>();
3131
private static readonly object FileLock = new object();
3232

33+
public static void RemoveUser(string uuid)
34+
{
35+
if (string.IsNullOrEmpty(uuid)) return;
36+
SeenPerUser.TryRemove(uuid, out _);
37+
}
38+
3339
public static void HandleEvent(NetPacketReader reader, NetPeer peer, byte eventType)
3440
{
3541
try

Basis Server/BasisNetworkServer/BasisNetworkPIPCamera.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ public static void RemovePlayer(int peerId)
239239

240240
BNL.Log($"PIP camera auto-destroyed for disconnected player {peerId}");
241241
}
242+
243+
foreach (var kvp in PIPStates)
244+
{
245+
kvp.Value.LastSentTimes.Remove(peerId);
246+
}
242247
}
243248

244249
public static void Reset()

Basis Server/BasisNetworkServer/BasisNetworkResourceManagement.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,35 @@ public static void Reset()
4242
}
4343
}
4444
}
45+
public static void RemovePeerResources(string uuid)
46+
{
47+
if (string.IsNullOrEmpty(uuid)) return;
48+
LocalLoadResource[] resourceArray = UshortNetworkDatabase.Values.ToArray();
49+
int length = resourceArray.Length;
50+
for (int index = 0; index < length; index++)
51+
{
52+
LocalLoadResource llr = resourceArray[index];
53+
if (llr.Persist || llr.UUIDOfCreator != uuid)
54+
{
55+
continue;
56+
}
57+
UnLoadResource unloadResource = new UnLoadResource
58+
{
59+
Mode = llr.Mode,
60+
LoadedNetID = llr.LoadedNetID
61+
};
62+
NetDataWriter writer = NetworkServer.RentWriter();
63+
unloadResource.Serialize(writer);
64+
NetworkServer.BroadcastMessageToClients(
65+
writer,
66+
BasisNetworkCommons.UnloadResourceChannel,
67+
NetworkServer.PeerSnapshot,
68+
DeliveryMethod.ReliableOrdered
69+
);
70+
NetworkServer.ReturnWriter(writer);
71+
UshortNetworkDatabase.Remove(llr.LoadedNetID, out LocalLoadResource Resource);
72+
}
73+
}
4574
public static void SendOutAllResources(NetPeer NewConnection)
4675
{
4776
LocalLoadResource[] Resource = UshortNetworkDatabase.Values.ToArray();

Basis Server/BasisNetworkServer/BasisServerHandleEvents.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ private static bool CleanupPeerSubsystems(NetPeer peer, int id)
7272
if (NetworkServer.AuthIdentity.NetIDToUUID(peer, out string uuid))
7373
{
7474
PermissionIntegration.RemovePlayerMeta(uuid);
75+
PermissionIntegration.EvictPermissionCache(uuid);
76+
BasisNetworkHandleErrorReport.RemoveUser(uuid);
77+
BasisNetworkResourceManagement.RemovePeerResources(uuid);
7578
}
7679

7780
NetworkServer.AuthIdentity.RemoveConnection(id);
@@ -83,6 +86,7 @@ private static bool CleanupPeerSubsystems(NetPeer peer, int id)
8386
BasisNetworkPreloadResourceManagement.RemovePeer(id);
8487
BasisNetworkServer.Security.BasisUserOpusBitrateStateManager.ClearForPeer(id);
8588
BasisServerP2PBroker.RemovePeer(id);
89+
BasisNetworkMessageProcessor.ClearPeerErrors(id);
8690

8791
return NetworkServer.AuthenticatedPeers.TryRemove(id, out _);
8892
}

Basis Server/BasisNetworkServer/Security/BasisDIDAuthIdentity.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class BasisDIDAuthIdentity : IAuthIdentity
2626
{
2727
internal readonly DidAuthentication DidAuth;
2828
public ConcurrentDictionary<int, OnAuth> AuthIdentity = new ConcurrentDictionary<int, OnAuth>();
29-
private readonly ConcurrentDictionary<NetPeer, CancellationTokenSource> _timeouts = new ConcurrentDictionary<NetPeer, CancellationTokenSource>();
29+
private readonly ConcurrentDictionary<int, CancellationTokenSource> _timeouts = new ConcurrentDictionary<int, CancellationTokenSource>();
3030
public ConcurrentDictionary<string, byte> Admins = new ConcurrentDictionary<string, byte>();
3131
public static readonly string FilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Configuration.ConfigFolderName, "admins.xml");
3232
public BasisDIDAuthIdentity()
@@ -130,7 +130,7 @@ public void ProcessConnection(Configuration Configuration, ConnectionRequest Con
130130
NetworkServer.ReturnWriter(Writer);
131131

132132
CancellationTokenSource cts = new CancellationTokenSource();
133-
_timeouts[newPeer] = cts;
133+
_timeouts[newPeer.Id] = cts;
134134
Task.Run(async () =>
135135
{
136136
await TimeOut(newPeer, UUID, cts);
@@ -158,9 +158,10 @@ public async Task TimeOut(NetPeer newPeer, string UUID, CancellationTokenSource
158158
try
159159
{
160160
await Task.Delay(NetworkServer.Configuration.AuthValidationTimeOutMiliseconds, cts.Token);
161-
if (!_timeouts.ContainsKey(newPeer)) return;
161+
if (!_timeouts.ContainsKey(newPeer.Id)) return;
162162
AuthIdentity.TryRemove(newPeer.Id, out _);
163-
_timeouts.TryRemove(newPeer, out _);
163+
_timeouts.TryRemove(newPeer.Id, out _);
164+
cts.Dispose();
164165
BNL.Log($"Authentication timeout for {UUID}.");
165166
BasisServerHandleEvents.RejectWithReason(newPeer, "Authentication timeout");
166167
newPeer.Disconnect();
@@ -173,9 +174,10 @@ private async void OnAuthReceived(NetPacketReader reader, NetPeer newPeer)
173174
try
174175
{
175176
// BNL.Log($"Authentication response received from {newPeer.Id}.");
176-
if (_timeouts.TryRemove(newPeer, out var cts))
177+
if (_timeouts.TryRemove(newPeer.Id, out var cts))
177178
{
178179
cts.Cancel();
180+
cts.Dispose();
179181
}
180182

181183
BytesMessage SignatureBytes = new BytesMessage();
@@ -243,6 +245,11 @@ public async Task<bool> RecvChallengeResponse(Response response, Challenge Chall
243245
public void RemoveConnection(int NetPeer)
244246
{
245247
AuthIdentity.TryRemove(NetPeer, out var authIdentity);
248+
if (_timeouts.TryRemove(NetPeer, out var cts))
249+
{
250+
try { cts.Cancel(); } catch { }
251+
cts.Dispose();
252+
}
246253
}
247254
public bool IsNetPeerAdmin(string UUID)
248255
{

Basis Server/BasisNetworkServer/Security/PermissionManager.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,20 @@ private void TouchAll()
601601
_dirty = true;
602602
}
603603

604+
public void EvictUserCache(string uuid)
605+
{
606+
if (string.IsNullOrEmpty(uuid)) return;
607+
_lock.EnterWriteLock();
608+
try
609+
{
610+
_cache.Remove(uuid);
611+
}
612+
finally
613+
{
614+
_lock.ExitWriteLock();
615+
}
616+
}
617+
604618
private EffectivePermissions GetEffective(string uuid)
605619
{
606620
_lock.EnterUpgradeableReadLock();
@@ -1071,6 +1085,11 @@ public static void RemovePlayerMeta(string uuid)
10711085
_playerMeta.TryRemove(uuid, out _);
10721086
}
10731087

1088+
public static void EvictPermissionCache(string uuid)
1089+
{
1090+
Manager.EvictUserCache(uuid);
1091+
}
1092+
10741093
public static bool HasValidRequirement(string uuid, string permNode)
10751094
{
10761095
bool hasPermission = Manager.Has(uuid, permNode);

0 commit comments

Comments
 (0)