private void _Refresh(LinkClient client, IEnumerable <int> groups = null) { /* Require lock */ var cid = client._id; var set = _joined.GetOrAdd(cid, _ => new HashSet <int>()); foreach (var i in set) { _set.TryGetValue(i, out var gro).AssertFatal("Failed to get group collection!"); gro.TryRemove(cid, out var val).AssertFatal(val == client, "Failed to remove client from group collection!"); if (gro.Count > 0) { continue; } _set.TryRemove(i, out var res).AssertFatal(res == gro, "Failed to remove empty group!"); } if (groups == null) { /* Client shutdown */ _joined.TryRemove(cid, out var res).AssertFatal(res == set, "Failed to remove group set!"); _clients.TryRemove(cid, out var val).AssertFatal(val == client, "Failed to remove client!"); return; } // Union with -> add range set.Clear(); set.UnionWith(groups); foreach (var i in groups) { var gro = _set.GetOrAdd(i, _ => new ConcurrentDictionary <int, LinkClient>()); gro.TryAdd(cid, client).AssertFatal("Failed to add client to group collection!"); } }
private async Task <Task> _AcceptClient(Socket socket) { LinkError _Check(int id) { if ((Links.Id < id && id < Links.DefaultId) == false) { return(LinkError.IdInvalid); } if (_clients.Count >= _climit) { return(LinkError.CountLimited); } return(_clients.TryAdd(id, null) ? LinkError.Success : LinkError.IdConflict); } var key = LinkCrypto.GetKey(); var blk = LinkCrypto.GetBlock(); var err = LinkError.None; var cid = 0; var iep = default(IPEndPoint); var oep = default(IPEndPoint); byte[] _Response(byte[] buf) { var rea = new Token(LinksHelper.Generator, buf); if (string.Equals(rea["protocol"].As <string>(), Links.Protocol, StringComparison.InvariantCultureIgnoreCase) == false) { throw new LinkException(LinkError.ProtocolMismatch); } cid = rea["source"].As <int>(); var mod = rea["rsa"]["modulus"].As <byte[]>(); var exp = rea["rsa"]["exponent"].As <byte[]>(); iep = rea["endpoint"].As <IPEndPoint>(); oep = (IPEndPoint)socket.RemoteEndPoint; err = _Check(cid); var rsa = RSA.Create(); var par = new RSAParameters() { Exponent = exp, Modulus = mod }; rsa.ImportParameters(par); var packet = LinksHelper.Generator.Encode(new { result = err, endpoint = oep, aes = new { key = rsa.Encrypt(key, RSAEncryptionPadding.OaepSHA1), iv = rsa.Encrypt(blk, RSAEncryptionPadding.OaepSHA1), } }); return(packet); } try { var buf = await socket.ReceiveAsyncExt().TimeoutAfter("Listener request timeout."); var res = _Response(buf); await socket.SendAsyncExt(res).TimeoutAfter("Listener response timeout."); err.AssertError(); } catch (Exception) { if (err == LinkError.Success) { _clients.TryRemove(cid, out var val).AssertFatal(val == null, "Failed to remove placeholder!"); } throw; } var clt = new LinkClient(cid, socket, iep, oep, key, blk); _clients.TryUpdate(cid, clt, null).AssertFatal("Failed to update client!"); clt.Received += _ClientReceived; clt.Disposed += _ClientDisposed; return(clt.Start()); }