Пример #1
0
        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!");
            }
        }
Пример #2
0
        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());
        }