Example #1
0
        private async Task ReceiveLoop(CancellationToken cancellationToken)
        {
            using var textReader     = new StreamReader(this.stream, messageEncoding);
            using var pushbackReader = new PushbackTextReader(textReader);
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();
                MessageBase message;
                try {
                    message = await TaskExtensions.WhenAny(
                        MessageBase.ReadMessage(pushbackReader, cancellationToken),
                        Task.Delay(TimeSpan.FromSeconds(ReceiveTimeoutSeconds), cancellationToken)
                        .Then(() => (MessageBase)null)
                        );
                } catch (JsonReaderException ex) {
                    Console.WriteLine(
                        $"Error reading message, aborting receive loop: {ex.Message}"
                        );

                    this.Shutdown();
                    return;
                }

                if (message == null)
                {
                    Console.WriteLine("Receive Timeout!");
                    // a timeout occurred!
                    this.Shutdown();
                    return;
                }

                var hubClient = this.hubContext.Clients.Client(this.hubConnectionId);

                if (hubClient == null)
                {
                    Console.WriteLine("Browser Disconnected!");
                    // Our client disconnected!
                    this.Shutdown();
                    return;
                }

                Console.WriteLine($"Message received: {message}");
                await hubClient.ReceiveMessage(message, cancellationToken);
            }
        }
Example #2
0
        public async Task <TroopConnectionStatus> Connect(
            String username,
            String passwordHash,
            CancellationToken cancellationToken)
        {
            // Authenticate
            var hostAddress =
                (await Dns.GetHostAddressesAsync(this.Troop.Hostname))
                .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            if (hostAddress == null)
            {
                return(TroopConnectionStatus.HostNotFound);
            }

            Console.WriteLine($"Setting remote endpoint to: {hostAddress}:{this.Troop.Port}");
            this.remoteEndpoint =
                new IPEndPoint(
                    hostAddress,
                    this.Troop.Port
                    );

            await this.tcpConnection.ConnectAsync(this.remoteEndpoint.Address, this.remoteEndpoint.Port);

            Console.WriteLine($"Local endpoint is: {this.tcpConnection.Client.LocalEndPoint}");
            this.stream = this.tcpConnection.GetStream();

            Console.WriteLine("Sending authentication message.");
            await this.SendMessage(new AuthenticateMessage(passwordHash, username), cancellationToken);

            var clientIdBuffer = new Byte[clientIdLength];
            var readBytes      = await TaskExtensions.WhenAny(
                this.stream.ReadAsync(clientIdBuffer, cancellationToken).AsTask(),
                Task.Delay(TimeSpan.FromSeconds(ConnectionTimeoutSeconds), cancellationToken).Then(() => - 1)
                );

            if (readBytes == -1)
            {
                Console.WriteLine("Connection timeout");
                return(TroopConnectionStatus.ConnectionTimeout);
            }
            else if (readBytes != clientIdLength)
            {
                Console.WriteLine("Invalid Authentication response");
                return(TroopConnectionStatus.InvalidData);
            }

            this.ClientId = Int32.Parse(messageEncoding.GetString(clientIdBuffer));
            Console.WriteLine($"Client id received: {this.ClientId}");

            switch (this.ClientId)
            {
            case -1:
                return(TroopConnectionStatus.LoginFailed);

            case -2:
                return(TroopConnectionStatus.MaxLoginsReached);

            case -3:
                return(TroopConnectionStatus.NameTaken);

            case -4:
                return(TroopConnectionStatus.VersionMismatch);

            default:
                if (this.ClientId < 0)
                {
                    return(TroopConnectionStatus.InvalidData);
                }

                break;
            }

            await this.SendMessage(
                new ConnectMessage(
                    messageId : 0,
                    sourceClientId : this.ClientId,
                    name : username,
                    hostname : this.Troop.Hostname,
                    port : (UInt16)this.Troop.Port,
                    dummy : true),
                cancellationToken
                );

            this.StartReceiver();

            return(TroopConnectionStatus.Success);
        }
Example #3
0
        public static async Task <TroopConnectionStatus> TestConnection(
            String hostname,
            UInt16 port,
            String passwordHash,
            CancellationToken cancellationToken)
        {
            // Authenticate
            var hostAddress =
                (await Dns.GetHostAddressesAsync(hostname))
                .FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

            if (hostAddress == null)
            {
                return(TroopConnectionStatus.HostNotFound);
            }

            var remoteEndpoint =
                new IPEndPoint(
                    hostAddress,
                    port
                    );

            try {
                using var tcpConnection = new TcpClient(AddressFamily.InterNetwork);

                var connected = await TaskExtensions.WhenAny(
                    tcpConnection.ConnectAsync(remoteEndpoint.Address, remoteEndpoint.Port).Then(() => true),
                    Task.Delay(TimeSpan.FromSeconds(ConnectionTimeoutSeconds), cancellationToken).Then(() => false)
                    );

                if (!connected)
                {
                    return(TroopConnectionStatus.ConnectionTimeout);
                }

                await using var stream = tcpConnection.GetStream();

                var messageData =
                    messageEncoding.GetBytes(new AuthenticateMessage(passwordHash, $"Test_{Guid.NewGuid()}").ToString());

                await stream.WriteAsync(messageData, 0, messageData.Length, cancellationToken);

                var clientIdBuffer = new Byte[clientIdLength];
                var readBytes      = await TaskExtensions.WhenAny(
                    stream.ReadAsync(clientIdBuffer, cancellationToken).AsTask(),
                    Task.Delay(TimeSpan.FromSeconds(ConnectionTimeoutSeconds), cancellationToken).Then(() => - 1)
                    );

                if (readBytes == -1)
                {
                    return(TroopConnectionStatus.ConnectionTimeout);
                }
                else if (readBytes != clientIdLength)
                {
                    return(TroopConnectionStatus.InvalidData);
                }

                var clientId = Int32.Parse(messageEncoding.GetString(clientIdBuffer));

                switch (clientId)
                {
                case -1:
                    return(TroopConnectionStatus.LoginFailed);

                case -2:
                    return(TroopConnectionStatus.MaxLoginsReached);

                case -3:
                    return(TroopConnectionStatus.NameTaken);

                case -4:
                    return(TroopConnectionStatus.VersionMismatch);

                default:
                    if (clientId < 0)
                    {
                        return(TroopConnectionStatus.InvalidData);
                    }

                    break;
                }

                return(TroopConnectionStatus.Success);
            } catch (SocketException ex) {
                if (ex.SocketErrorCode == SocketError.ConnectionRefused)
                {
                    return(TroopConnectionStatus.ConnectionRefused);
                }
                else
                {
                    return(TroopConnectionStatus.UnknownError);
                }
            }
        }