/// <summary>
        /// Verifies that we are currectly connected to the server. If not but we *wish* to be connected,
        /// it attempts to establish the connection. If not and we don't wish to be connected, it fails.
        /// </summary>
        private async Task EnsureConnectedAsync()
        {
            if (_client != null)
            {
                // We are likely to still be connected.
                return;
            }
            if (!_shouldBeConnected)
            {
                throw new Exception("A method was called that requires an IGS connection but the 'Connect()' method was not called; or maybe 'Disconnect()' was called.");
            }
            _client = new TcpSocketClient();
            try
            {
                await _client.ConnectAsync(_hostname, _port);

                _streamWriter           = new StreamWriter(_client.WriteStream);
                _streamReader           = new StreamReader(_client.ReadStream);
                _streamWriter.AutoFlush = true;
#pragma warning disable 4014
                HandleIncomingData(_streamReader).ContinueWith(t =>
                {
                    throw new Exception("If this is connection error, then fine, otherwise throw up.");
                }, TaskContinuationOptions.OnlyOnFaulted);
#pragma warning restore 4014
                _composure = IgsComposure.InitialHandshake;
                _streamWriter.WriteLine("guest");
                _streamWriter.WriteLine("toggle client on");
                await WaitUntilComposureChangesAsync();
            }
            catch
            {
                throw new Exception("We failed to establish a connection with the server.");
            }
        }
        private Task WaitUntilComposureChangesAsync()
        {
            IgsComposure originalComposure = _composure;

            return(Task.Run(() =>
            {
                lock (_mutexComposureRegained)
                {
                    while (_composure == originalComposure)
                    {
                        Monitor.Wait(_mutexComposureRegained);
                    }
                }
            }));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Connects to IGS at the specified host and port and logs in as a guest account. If we are already connected,
        /// then this method does nothing.
        /// </summary>
        /// <param name="hostname">The hostname to connect to.</param>
        /// <param name="port">The port to connect to.</param>
        /// <returns></returns>
        public async Task <bool> ConnectAsync(string hostname = ServerLocations.IgsPrimary, int port = ServerLocations.IgsPortPrimary)
        {
            _hostname = hostname;
            _port     = port;
            try
            {
                if (_client != null && ConnectionEstablished)
                {
                    // We are likely to still be connected.
                    return(true);
                }
                _client = new TcpSocketClient();
                try
                {
                    Composure = IgsComposure.InitialHandshake;
                    await _client.ConnectAsync(_hostname, _port);

                    _streamWriter           = new StreamWriter(_client.WriteStream);
                    _streamReader           = new StreamReader(_client.ReadStream);
                    _streamWriter.AutoFlush = true;
#pragma warning disable 4014
                    HandleIncomingData(_streamReader).ContinueWith(t =>
                    {
                        // Cancel everything.
                        ConnectionLost();
                    }, TaskContinuationOptions.OnlyOnFaulted);
#pragma warning restore 4014
                    _streamWriter.WriteLine("guest");
                    _streamWriter.WriteLine("toggle client on");
                    await WaitUntilComposureChangesAsync();
                }
                catch
                {
                    Composure = IgsComposure.Disconnected;
                    return(false);
                }
                ConnectionEstablished = true;
            }
            catch
            {
                Composure = IgsComposure.Disconnected;
                return(false);
            }
            return(true);
        }
        /// <summary>
        /// Unlike other methods, this is not always thread-safe.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        public async Task <bool> LoginAsync(string username, string password)
        {
            if (username == null)
            {
                throw new ArgumentNullException(nameof(username));
            }
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }
            await EnsureConnectedAsync();

            _composure  = IgsComposure.LoggingIn;
            _username   = username;
            _password   = password;
            _loginError = null;
            ClearConnectionInformation();
            _streamWriter.WriteLine("login");
            _streamWriter.WriteLine(_username);
            _streamWriter.WriteLine(_password);
            await WaitUntilComposureChangesAsync();

            if (_composure == IgsComposure.Confused)
            {
                await _client.DisconnectAsync();

                _client = null;
                return(false);
            }
            if (_loginError != null)
            {
                OnIncomingLine("LOGIN ERROR: " + _loginError);
                return(false);
            }
            await MakeRequestAsync("toggle quiet true");
            await MakeRequestAsync("toggle newundo true");
            await MakeRequestAsync("toggle verbose false");

            return(true);
        }
Exemplo n.º 5
0
        private void ConnectionLost()
        {
            LoggedIn = false;
            if (Composure == IgsComposure.Disconnected)
            {
                return;
                // Don't do this twice.
                // Thread safety problems may occur. Oh well, it's networking. Hopefully they won't.
                // If yes, we should eliminate the possibilities for connection loss elsewehere and maybe ensure that a single
                // point of connection failure exists, possibly in OnFaulted. We'll see.
            }
            _client               = null;
            Composure             = IgsComposure.Disconnected;
            ConnectionEstablished = false;
            foreach (var game in _availableConnectors)
            {
                game.Value.Disconnect();
            }
            Data.GamesInProgress.Clear();
            Data.OnlineUsers.Clear();
            this.GamesYouHaveOpened.Clear();
            this.GamesBeingObserved.Clear();
            _availableConnectors.Clear();
            IgsRequest notYetHandledRequest;

            while (_outgoingRequests.TryDequeue(out notYetHandledRequest))
            {
                notYetHandledRequest.Disconnect();
            }
            lock (_mutex)
            {
                _requestInProgress?.Disconnect();
                _requestInProgress = null;
            }

            Events.RaiseDisconnected();
        }
Exemplo n.º 6
0
        /// <summary>
        /// Unlike other methods, this is not always thread-safe.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <param name="password">The password.</param>
        public async Task <bool> LoginAsync(string username, string password)
        {
            if (username == null)
            {
                throw new ArgumentNullException(nameof(username));
            }
            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }
            try
            {
                Events.RaiseLoginPhaseChanged(IgsLoginPhase.Connecting);
                if (!ConnectionEstablished)
                {
                    if (!await ConnectAsync())
                    {
                        return(false);
                    }
                }
                Events.RaiseLoginPhaseChanged(IgsLoginPhase.LoggingIn);
                Composure   = IgsComposure.LoggingIn;
                _username   = username;
                _password   = password;
                _loginError = null;
                ClearConnectionInformation();
                _streamWriter.WriteLine("login");
                _streamWriter.WriteLine(_username);
                _streamWriter.WriteLine(_password);
                await WaitUntilComposureChangesAsync();

                if (Composure == IgsComposure.Confused)
                {
                    await _client.DisconnectAsync();

                    _client = null;
                    Events.RaiseLoginComplete(false);
                    return(false);
                }
                if (_loginError != null)
                {
                    Events.OnIncomingLine("LOGIN ERROR: " + _loginError);
                    Events.RaiseLoginComplete(false);
                    return(false);
                }
                Events.RaiseLoginPhaseChanged(IgsLoginPhase.SendingInitialBurst);
                await MakeRequestAsync("toggle quiet true");
                await MakeRequestAsync("id omegaGo");
                await MakeRequestAsync("toggle newundo true");
                await MakeRequestAsync("toggle verbose false");

                Events.RaiseLoginPhaseChanged(IgsLoginPhase.RefreshingGames);
                await Commands.ListGamesInProgressAsync();

                Events.RaiseLoginPhaseChanged(IgsLoginPhase.RefreshingUsers);
                await Commands.ListOnlinePlayersAsync();

                Events.RaiseLoginPhaseChanged(IgsLoginPhase.Done);
                LoggedIn = true;
                Events.RaiseLoginComplete(true);
                return(true);
            }
            catch
            {
                await DisconnectAsync();

                return(false);
            }
        }