public static async Task <DBusConnection> ConnectAsync(ClientSetupResult connectionContext, Action <Exception> onDisconnect, CancellationToken cancellationToken, IEnumerable <IClientObjectProvider> clientProviders) { var _entries = AddressEntry.ParseEntries(connectionContext.ConnectionAddress); if (_entries.Length == 0) { throw new ArgumentException("No addresses were found", nameof(connectionContext.ConnectionAddress)); } Guid _serverId = Guid.Empty; IMessageStream stream = null; var index = 0; while (index < _entries.Length) { AddressEntry entry = _entries[index++]; _serverId = entry.Guid; try { stream = await Transport.ConnectAsync(entry, connectionContext, cancellationToken) .TimeoutAfter(connectionContext.InitialTimeout) .ConfigureAwait(false); } catch { if (index < _entries.Length) { continue; } throw; } break; } return(await CreateAndConnectAsync(stream, onDisconnect, clientProviders, true, connectionContext.InitialTimeout)); }
private async Task <DBusConnection> DoConnectAsync() { Task <DBusConnection> connectionTask = null; bool alreadyConnecting = false; lock (_gate) { if (_disposed) { ThrowDisposed(); } if (_connectionType == ConnectionType.ClientManual) { if (_state != ConnectionState.Created) { throw new InvalidOperationException("Can only connect once"); } } else { if (_state == ConnectionState.Connecting || _state == ConnectionState.Connected) { connectionTask = _dbusConnectionTask; alreadyConnecting = true; } } if (!alreadyConnecting) { _connectCts = new CancellationTokenSource(); _dbusConnectionTcs = new TaskCompletionSource <DBusConnection>(); _dbusConnectionTask = _dbusConnectionTcs.Task; connectionTask = _dbusConnectionTask; _state = ConnectionState.Connecting; EmitConnectionStateChanged(); } } if (alreadyConnecting) { return(await connectionTask); } DBusConnection connection; object disposeUserToken = NoDispose; try { ClientSetupResult connectionContext = await _connectFunction(); disposeUserToken = connectionContext.TeardownToken; connection = await DBusConnection.ConnectAsync(connectionContext, OnDisconnect, _connectCts.Token); } catch (ConnectException ce) { if (disposeUserToken != NoDispose) { _disposeAction?.Invoke(disposeUserToken); } Disconnect(dispose: false, exception: ce); throw; } catch (Exception e) { if (disposeUserToken != NoDispose) { _disposeAction?.Invoke(disposeUserToken); } var ce = new ConnectException(e.Message, e); Disconnect(dispose: false, exception: ce); throw ce; } lock (_gate) { if (_state == ConnectionState.Connecting) { _disposeUserToken = disposeUserToken; _dbusConnection = connection; _connectCts.Dispose(); _connectCts = null; _state = ConnectionState.Connected; _dbusConnectionTcs.SetResult(connection); _dbusConnectionTcs = null; EmitConnectionStateChanged(); } else { connection.Dispose(); if (disposeUserToken != NoDispose) { _disposeAction?.Invoke(disposeUserToken); } } ThrowIfNotConnected(); } return(connection); }