public EndPointListener(
            IPAddress address,
            int port,
            bool secure,
            string certFolderPath,
            X509Certificate2 defaultCert
            )
        {
            if (secure)
            {
                _secure = secure;
                _cert   = getCertificate(port, certFolderPath, defaultCert);
                if (_cert == null)
                {
                    throw new ArgumentException("Server certificate not found.");
                }
            }

            _endpoint = new IPEndPoint(address, port);
            _socket   = SocketUtilsFactory.Utils.CreateSocket(address);
            _socket.Bind(_endpoint);
            _socket.Listen(500);
            var args = SocketUtilsFactory.Utils.CreateSocketAsyncEventArgs();

            args.UserToken  = this;
            args.Completed += onAccept;
            _socket.AcceptAsync(args);
            _prefixes     = new Dictionary <ListenerPrefix, HttpListener> ();
            _unregistered = new Dictionary <HttpConnection, HttpConnection> ();
        }
示例#2
0
        private async Task AcceptClientAsync()
        {
            SocketAwaitable awaitable = Pools.SocketAwaitable.Take();

            try
            {
                while (!_cts.IsCancellationRequested)
                {
                    var error = await _listenerSocket.AcceptAsync(awaitable);

                    if (error == SocketError.ConnectionReset)
                    {
                        continue;
                    }

                    if (error == SocketError.OperationAborted)
                    {
                        _log.Error($"{error} returned by AcceptClientAsync - requesting cancellation and shutting down.");
                        _cts.Cancel();
                        break;
                    }

                    if (error != SocketError.Success)
                    {
                        _log.Error($"AcceptAsync failed with error: {error}");
                        continue;
                    }

                    var socket = new TcpSocket(awaitable.EventArgs.AcceptSocket);
                    socket.NoDelay = true;

                    // Null it now so we don't dispose of it in the finally clause.
                    awaitable.EventArgs.AcceptSocket = null;

                    var client = _clientFactory();
                    var ep     = socket.RemoteEndPoint;
                    client.SetSocket(socket);

                    _lock.EnterWriteLock();
                    try
                    {
                        _clients.Add(client);
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }

                    _log.Debug($"Client from {ep} successfully connected.");
                }
            }
            finally
            {
                awaitable.EventArgs.AcceptSocket?.Dispose();
                awaitable.EventArgs.AcceptSocket = null;

                Pools.SocketAwaitable.Return(awaitable);
            }
        }
示例#3
0
        private async Task OpenInternal()
        {
            _isOpened = true;
            _recorder.RecordInfo(nameof(NetworkPoint), $"NetworkPoint opened {(_sListener.LocalEndPoint).Address}:{(_sListener.LocalEndPoint).Port}");

            while (_isOpened)
            {
                _sListener.Listen(10);
                ISocket socket = await _sListener.AcceptAsync();

                SafeExecution.TryCatch(() => ConnectionAcceptedHandler(socket), ExceptionHandler);
            }
        }
示例#4
0
        private Func <AddressFamily, SocketType, ProtocolType, ISocket> ArrangeSocketFactory(ISocket socketMock = default, bool returnTask = true)
        {
            if (socketMock == default)
            {
                socketMock = Mock.Create <ISocket>();
            }

            if (returnTask)
            {
                var tcs = new TaskCompletionSource <ISocket>();
                Mock.Arrange(() => socketMock.AcceptAsync()).Returns(tcs.Task);
            }

            var factory = Mock.Create <Func <AddressFamily, SocketType, ProtocolType, ISocket> >();

            Mock.Arrange(() => factory.Invoke(default, default, default))
示例#5
0
        /// <summary>
        /// Begins an asynchronous read operation that uses these event args.
        /// </summary>
        /// <param name="socket">The socket.</param>
        /// <param name="cancellationToken">A token to monitor for cancellation requests. The default value is <see cref="System.Threading.CancellationToken.None" />.</param>
        /// <returns>
        /// A <see cref="Task{ISocket}" /> that represents the asynchronous accept operation.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">EventArgs already in use.</exception>
        public Task <ISocket> AcceptAsync(ISocket socket, CancellationToken cancellationToken = default(CancellationToken))
        {
            var completionSource = new TaskCompletionSource <ISocket>();

            if (Interlocked.CompareExchange(ref _completionSource, completionSource, null) != null)
            {
                throw new InvalidOperationException(Properties.Resources.InvalidOperation_ObjectInUse);
            }

            _cancelled    = false;
            _registration = cancellationToken.Register(Cancel);

            if (!socket.AcceptAsync(this))
            {
                OnCompleted(this);
            }

            return(completionSource.Task);
        }
示例#6
0
        public static async Task <SocketError> AcceptAsync(this ISocket socket, SocketAwaitable awaitable)
        {
            Requires.NotNull(awaitable, nameof(awaitable));

            try
            {
                awaitable.Reset();

                if (!socket.AcceptAsync(awaitable.EventArgs))
                {
                    awaitable.CompleteSynchronously();
                }

                await awaitable;
                return(awaitable.EventArgs.SocketError);
            }
            catch (ObjectDisposedException)
            {
                return(SocketError.ConnectionAborted);
            }
        }
示例#7
0
        /// <summary>
        /// Opens the asynchronous.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="bearerTokenPredicate">The bearer token predicate.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        /// <exception cref="Exception">Invalid Bearer Token</exception>
        /// <exception cref="ArgumentOutOfRangeException">method</exception>
        public async Task OpenAsync(HttpContext context, ILogger logger, Func <string, bool> bearerTokenPredicate = null, CancellationToken?cancellationToken = null)
        {
            var correlation = Guid.NewGuid();
            var webSockets  = context.WebSockets;

            if (!webSockets.IsWebSocketRequest)
            {
                context.Response.StatusCode = 405;
                return;
            }
            context.Response.StatusCode = 101;
            var ws = await _socket.AcceptAsync(webSockets).ConfigureAwait(false);

            AutomaClient client = null;

            try
            {
                var bearerToken = await ws.ReceiveAsync <string>(cancellationToken).ConfigureAwait(false);

                if (!bearerTokenPredicate?.Invoke(bearerToken) ?? true)
                {
                    throw new Exception("Invalid Bearer Token");
                }
                var opened = true;
                while (opened && !context.RequestAborted.IsCancellationRequested)
                {
                    var method = await ws.ReceiveAsync <ProxyMethod>(cancellationToken).ConfigureAwait(false);

                    switch (method)
                    {
                    case ProxyMethod.Open:
                    {
                        var args = await ws.ReceiveObjectAsync <Args>(cancellationToken).ConfigureAwait(false);

                        logger?.LogInformation($"[{correlation}] Open: {((JsonElement)args["_base"]).GetProperty("Type").GetString()}");
                        client = AutomaClient.Parse(args);
                        break;
                    }

                    case ProxyMethod.Custom:
                    {
                        var registration = await ws.ReceiveAsync <Type>(cancellationToken).ConfigureAwait(false);

                        var param = await ws.ReceiveTypedAsync(cancellationToken).ConfigureAwait(false);

                        var tag = await ws.ReceiveTypedAsync(cancellationToken).ConfigureAwait(false);

                        logger?.LogInformation($"[{correlation}] Custom: {registration?.Name}");
                        var(obj, custom) = await client.Automa.CustomAsync(registration, param, tag).ConfigureAwait(false);

                        await ws.SendBarrier(false, cancellationToken).ConfigureAwait(false);

                        if (custom is ICustomWithTransfer customWithTransfer)
                        {
                            await customWithTransfer.SendAsync(ws, param).ConfigureAwait(false);

                            await ws.SendBarrier(false, cancellationToken).ConfigureAwait(false);
                        }
                        await ws.SendTypedAsync(obj, cancellationToken).ConfigureAwait(false);

                        break;
                    }

                    case ProxyMethod.Login:
                    {
                        var credential = await ws.ReceiveObjectAsync <NetworkCredential>(cancellationToken).ConfigureAwait(false);

                        client.ServiceLogin    = credential.UserName;
                        client.ServicePassword = credential.Password;
                        var tag = await ws.ReceiveTypedAsync(cancellationToken).ConfigureAwait(false);

                        logger?.LogInformation($"[{correlation}] Login: {client.ServiceLogin}");
                        await client.Automa.LoginAsync(tag).ConfigureAwait(false);

                        break;
                    }

                    case ProxyMethod.SelectApplication:
                    {
                        var application = await ws.ReceiveAsync <string>(cancellationToken).ConfigureAwait(false);

                        var tag = await ws.ReceiveTypedAsync(cancellationToken).ConfigureAwait(false);

                        logger?.LogInformation($"[{correlation}] SelectApplication: {application}");
                        var obj = await client.Automa.SelectApplicationAsync(application, tag).ConfigureAwait(false);

                        await ws.SendBarrier(false, cancellationToken).ConfigureAwait(false);

                        await ws.SendTypedAsync(obj, cancellationToken).ConfigureAwait(false);

                        break;
                    }

                    case ProxyMethod.SetDeviceAccessToken:
                    {
                        var url = await ws.ReceiveAsync <string>(cancellationToken).ConfigureAwait(false);

                        var code = await ws.ReceiveAsync <string>(cancellationToken).ConfigureAwait(false);

                        var tag = await ws.ReceiveTypedAsync(cancellationToken).ConfigureAwait(false);

                        logger?.LogInformation($"[{correlation}] SetDeviceAccessTokenAsync: {url}, {code}");
                        await client.Automa.SetDeviceAccessTokenAsync(url, code, tag).ConfigureAwait(false);

                        break;
                    }

                    case ProxyMethod.GetCookies:
                    {
                        logger?.LogInformation($"[{correlation}] GetCookies");
                        await ws.SendBarrier(false, cancellationToken).ConfigureAwait(false);

                        await ws.SendObjectAsync(client.Automa.Cookies, cancellationToken).ConfigureAwait(false);

                        break;
                    }

                    case ProxyMethod.Dispose:
                    {
                        logger?.LogInformation($"[{correlation}] Dispose");
                        opened = false;
                        break;
                    }

                    default: throw new ArgumentOutOfRangeException(nameof(method), method.ToString());
                    }
                    await ws.SendBarrier(true, cancellationToken).ConfigureAwait(false);
                }
            }
            catch (Exception e)
            {
                logger?.LogCritical(e, $"{correlation}>Exception");
                await ws.SendExceptionAsync(e, cancellationToken);
            }
            finally
            {
                client?.Dispose();
            }
            logger?.LogInformation($"[{correlation}] Done");
        }