using System.Collections.Concurrent; using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; using PCC.App.Security; using PCC.Common.AssemblyInject.Interfaces; using PCC.Common.EventBus; namespace PCC.App.Tpm; // Handshake 1 → Public Key SHA256 // Handshake 2 ← ACK for Yes or No(close connection) // *Complete Handshake // SendText 1 → Payload // SendText 2 ← ACK // ACK: SHA256(incoming payload) public abstract class TrustedPeerManager(IPeerInfoProvider peerInfoProvider, IEventBus eventBus, ILogger logger) : IAssemblyInjectSyncInitStarStop { private const int NONCE_LENGTH_BYTES = 16; private const int NONCE_EXPIRE_SECOND = 60; private const int NONCE_SKEW_SECOND = 30; private readonly SocketConnectionContextFactory _connectionContextFactory = new(new(), logger); private readonly ConcurrentDictionary _localPeers = new(); private TimestampNonceManager? _nonceManager; public void Init() { } public void Start() { _nonceManager = new(NONCE_LENGTH_BYTES - TimestampNonceManager.TimestampLength, TimeSpan.FromMicroseconds(NONCE_EXPIRE_SECOND), TimeSpan.FromSeconds(NONCE_SKEW_SECOND)); foreach (var item in peerInfoProvider.PeerInfo) { _localPeers[item.PeerId] = new LocalPeerManager(_connectionContextFactory, _nonceManager, item, eventBus, logger); } foreach (var item in _localPeers.Values) item.Start(); } public void Stop() { foreach (var item in _localPeers.Values) item.Stop(); _localPeers.Clear(); _nonceManager?.Dispose(); } public void AddOrReplaceLocalPeer(ILocalPeerInfo localPeerInfo) { RemoveLocalPeer(localPeerInfo.PeerId); _localPeers[localPeerInfo.PeerId] = new LocalPeerManager(_connectionContextFactory, _nonceManager, localPeerInfo, eventBus, logger); } public bool AddOrReplaceRemotePeer(string localPeerId, IRemotePeerInfo remotePeerInfo) { if (!_localPeers.TryGetValue(localPeerId, out var localPeerManager)) return false; localPeerManager.AddOrReplaceRemotePeer(remotePeerInfo); return true; } public bool RemoveLocalPeer(string localPeerId) { if (_localPeers.Remove(localPeerId, out var localPeerManager) == false) return false; localPeerManager.Stop(); return true; } public bool RemoveRemotePeer(string localPeerId, string remotePeerId) { return _localPeers.TryGetValue(localPeerId, out var localPeerManager) && localPeerManager.RemoveRemotePeer(remotePeerId); } public bool ConnectToPeerAsync(string localPeerId, string remotePeerId) { return _localPeers.TryGetValue(localPeerId, out var localPeerManager) && localPeerManager.ConnectToRemotePeer(remotePeerId); } public bool SendToPeer(string localPeerId, string remotePeerId, byte[] payload) { return _localPeers.TryGetValue(localPeerId, out var localPeerManager) && localPeerManager.SendToRemotePeer(remotePeerId, payload); } }