public async void NavigateFromConnectionResult(ConnectionResult result)
        {
            // Startup wizard
            if (result.State == ConnectionState.Unavailable || result.State == ConnectionState.ConnectSignIn)
            {
                await Dispatcher.InvokeAsync(async () => await _appHost.NavigationService.Navigate(new StartupWizardPage(_appHost.NavigationService, _appHost.ConnectionManager, _appHost.PresentationManager, _logger)));
            }

            else if (result.State == ConnectionState.ServerSelection)
            {
                await Dispatcher.InvokeAsync(async () => await _appHost.NavigationService.Navigate(new ServerSelectionPage(_appHost.ConnectionManager, _appHost.PresentationManager, result.Servers, _appHost.NavigationService, _logger)));
            }

            else if (result.State == ConnectionState.ServerSignIn)
            {
                //await Dispatcher.InvokeAsync(async () => await _appHost.NavigationService.Navigate(new ServerSelectionPage(_appHost.ConnectionManager, _appHost.PresentationManager, result.Servers, _appHost.NavigationService, _logger)));
                await _appHost.NavigationService.NavigateToLoginPage(result.ApiClient);
            }

            else if (result.State == ConnectionState.SignedIn)
            {
                await _appHost.SessionManager.ValidateSavedLogin(result);
            }
        }
Example #2
0
        public async Task ValidateSavedLogin(ConnectionResult result)
        {
            CurrentUser = await result.ApiClient.GetUserAsync(result.ApiClient.CurrentUserId);

            // TODO: Switch to check for ConnectUser
            if (result.Servers.Any(i => !string.IsNullOrEmpty(i.ExchangeToken)))
            {
                _config.Configuration.RememberLogin = true;
                _config.SaveConfiguration();
            }
            
            await AfterLogin();
        }
        private async Task OnSuccessfulConnection(ServerInfo server,
            ConnectionOptions options,
            PublicSystemInfo systemInfo,
            ConnectionResult result,
            ConnectionMode connectionMode,
            CancellationToken cancellationToken)
        {
            server.ImportInfo(systemInfo);

            var credentials = await _credentialProvider.GetServerCredentials().ConfigureAwait(false);

            if (!string.IsNullOrWhiteSpace(credentials.ConnectAccessToken))
            {
                await EnsureConnectUser(credentials, cancellationToken).ConfigureAwait(false);

                if (!string.IsNullOrWhiteSpace(server.ExchangeToken))
                {
                    await AddAuthenticationInfoFromConnect(server, connectionMode, credentials, cancellationToken).ConfigureAwait(false);
                }
            }

            if (!string.IsNullOrWhiteSpace(server.AccessToken))
            {
                await ValidateAuthentication(server, connectionMode, options, cancellationToken).ConfigureAwait(false);
            }

            credentials.AddOrUpdateServer(server);

            if (options.UpdateDateLastAccessed)
            {
                server.DateLastAccessed = DateTime.UtcNow;
            }
            server.LastConnectionMode = connectionMode;

            await _credentialProvider.SaveServerCredentials(credentials).ConfigureAwait(false);

            result.ApiClient = GetOrAddApiClient(server, connectionMode);
            result.State = string.IsNullOrEmpty(server.AccessToken) ?
                ConnectionState.ServerSignIn :
                ConnectionState.SignedIn;

            ((ApiClient)result.ApiClient).EnableAutomaticNetworking(server, connectionMode, _networkConnectivity);

            if (result.State == ConnectionState.SignedIn)
            {
                AfterConnected(result.ApiClient, options);
            }

            CurrentApiClient = result.ApiClient;

            result.Servers.Add(server);

            if (Connected != null)
            {
                Connected(this, new GenericEventArgs<ConnectionResult>(result));
            }
        }
        public async Task<ConnectionResult> Connect(ServerInfo server, ConnectionOptions options, CancellationToken cancellationToken = default(CancellationToken))
        {
            var result = new ConnectionResult
            {
                State = ConnectionState.Unavailable
            };

            PublicSystemInfo systemInfo = null;
            var connectionMode = ConnectionMode.Manual;

            var tests = new[] { ConnectionMode.Manual, ConnectionMode.Local, ConnectionMode.Remote }.ToList();

            // If we've connected to the server before, try to optimize by starting with the last used connection mode
            if (server.LastConnectionMode.HasValue)
            {
                tests.Remove(server.LastConnectionMode.Value);
                tests.Insert(0, server.LastConnectionMode.Value);
            }

            var isLocalNetworkAvailable = _networkConnectivity.GetNetworkStatus().GetIsAnyLocalNetworkAvailable();

            // Kick off wake on lan on a separate thread (if applicable)
            var sendWakeOnLan = server.WakeOnLanInfos.Count > 0 && isLocalNetworkAvailable;

            var wakeOnLanTask = sendWakeOnLan ?
                Task.Run(() => WakeServer(server, cancellationToken), cancellationToken) :
                Task.FromResult(true);

            var wakeOnLanSendTime = DateTime.Now;

            foreach (var mode in tests)
            {
                _logger.Debug("Attempting to connect to server {0}. ConnectionMode: {1}", server.Name, mode.ToString());

                if (mode == ConnectionMode.Local)
                {
                    // Try connect locally if there's a local address,
                    // and we're either on localhost or the device has a local connection
                    if (!string.IsNullOrEmpty(server.LocalAddress) && isLocalNetworkAvailable)
                    {
                        // Try to connect to the local address
                        systemInfo = await TryConnect(server.LocalAddress, 8000, cancellationToken).ConfigureAwait(false);
                    }
                }
                else if (mode == ConnectionMode.Manual)
                {
                    // Try manual address if there is one, but only if it's different from the local/remote addresses
                    if (!string.IsNullOrEmpty(server.ManualAddress)
                        && !string.Equals(server.ManualAddress, server.LocalAddress, StringComparison.OrdinalIgnoreCase)
                        && !string.Equals(server.ManualAddress, server.RemoteAddress, StringComparison.OrdinalIgnoreCase))
                    {
                        // Try to connect to the local address
                        systemInfo = await TryConnect(server.ManualAddress, 15000, cancellationToken).ConfigureAwait(false);
                    }
                }
                else if (mode == ConnectionMode.Remote)
                {
                    if (!string.IsNullOrEmpty(server.RemoteAddress))
                    {
                        systemInfo = await TryConnect(server.RemoteAddress, 15000, cancellationToken).ConfigureAwait(false);
                    }
                }

                if (systemInfo != null)
                {
                    connectionMode = mode;
                    break;
                }
            }

            if (systemInfo == null && !string.IsNullOrEmpty(server.LocalAddress) && isLocalNetworkAvailable && sendWakeOnLan)
            {
                await wakeOnLanTask.ConfigureAwait(false);

                // After wake on lan finishes, make sure at least 10 seconds have elapsed since the time it was first sent out
                var waitTime = TimeSpan.FromSeconds(10).TotalMilliseconds -
                               (DateTime.Now - wakeOnLanSendTime).TotalMilliseconds;

                if (waitTime > 0)
                {
                    await Task.Delay(Convert.ToInt32(waitTime, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false);
                }

                systemInfo = await TryConnect(server.LocalAddress, 15000, cancellationToken).ConfigureAwait(false);
            }

            if (systemInfo != null)
            {
                await OnSuccessfulConnection(server, options, systemInfo, result, connectionMode, cancellationToken)
                        .ConfigureAwait(false);
            }

            result.ConnectUser = ConnectUser;
            return result;
        }
        /// <summary>
        /// Loops through a list of servers and returns the first that is available for connection
        /// </summary>
        private async Task<ConnectionResult> Connect(List<ServerInfo> servers, CancellationToken cancellationToken)
        {
            servers = servers
               .OrderByDescending(i => i.DateLastAccessed)
               .ToList();

            if (servers.Count == 1)
            {
                _logger.Debug("1 server in the list.");

                var result = await Connect(servers[0], cancellationToken).ConfigureAwait(false);

                if (result.State == ConnectionState.Unavailable)
                {
                    result.State = result.ConnectUser == null ?
                        ConnectionState.ConnectSignIn :
                        ConnectionState.ServerSelection;
                }

                return result;
            }

            var firstServer = servers.FirstOrDefault();
            // See if we have any saved credentials and can auto sign in
            if (firstServer != null && !string.IsNullOrEmpty(firstServer.AccessToken))
            {
                var result = await Connect(firstServer, cancellationToken).ConfigureAwait(false);

                if (result.State == ConnectionState.SignedIn)
                {
                    return result;
                }
            }

            var finalResult = new ConnectionResult
            {
                Servers = servers,
                ConnectUser = ConnectUser
            };

            finalResult.State = servers.Count == 0 && finalResult.ConnectUser == null ?
                ConnectionState.ConnectSignIn :
                ConnectionState.ServerSelection;

            return finalResult;
        }
        private async Task<ConnectionResult> GetOfflineResult()
        {
            var credentials = await _credentialProvider.GetServerCredentials().ConfigureAwait(false);

            var offlineUsers = await GetOfflineUsers(credentials, true).ConfigureAwait(false);

            var result = new ConnectionResult
            {
                State = ConnectionState.OfflineSignIn
            };

            // If there's only one valid offline user, log them straight in
            if (offlineUsers.Count == 1)
            {
                result.State = ConnectionState.OfflineSignedIn;
                result.OfflineUser = offlineUsers[0].Item3;
            }

            return result;
        }