Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
# Hack to support latest prerelease dotnet SDK, https://github.com/dotnet/installer/issues/12230#issuecomment-936348246
MSBuildEnableWorkloadResolver: false
# Windows comes with PG pre-installed, and defines the PGPASSWORD environment variable. Remove it as it interferes
# with some of our tests
PGPASSWORD: ""

jobs:
build:
Expand Down
15 changes: 9 additions & 6 deletions src/Npgsql/Internal/NpgsqlConnector.Auth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async Task Authenticate(string username, NpgsqlTimeout timeout, bool async, Canc

async Task AuthenticateCleartext(string username, bool async, CancellationToken cancellationToken = default)
{
var passwd = GetPassword(username);
var passwd = await GetPassword(username, async, cancellationToken);
if (passwd == null)
throw new NpgsqlException("No password has been provided but the backend requires one (in cleartext)");

Expand Down Expand Up @@ -155,7 +155,7 @@ async Task AuthenticateSASL(List<string> mechanisms, string username, bool async
throw new NpgsqlException("Unable to bind to SCRAM-SHA-256-PLUS, check logs for more information");
}

var passwd = GetPassword(username) ??
var passwd = await GetPassword(username, async, cancellationToken) ??
throw new NpgsqlException($"No password has been provided but the backend requires one (in SASL/{mechanism})");

// Assumption: the write buffer is big enough to contain all our outgoing messages
Expand Down Expand Up @@ -260,7 +260,7 @@ static byte[] HMAC(byte[] data, string key)

async Task AuthenticateMD5(string username, byte[] salt, bool async, CancellationToken cancellationToken = default)
{
var passwd = GetPassword(username);
var passwd = await GetPassword(username, async, cancellationToken);
if (passwd == null)
throw new NpgsqlException("No password has been provided but the backend requires one (in MD5)");

Expand Down Expand Up @@ -442,13 +442,15 @@ public override long Position

class AuthenticationCompleteException : Exception { }

string? GetPassword(string username)
async ValueTask<string?> GetPassword(string username, bool async, CancellationToken cancellationToken = default)
{
var password = Settings.Password;
if (password != null)
var password = await _dataSource.GetPasswordAsync(async, cancellationToken);

if (password is not null)
return password;

if (ProvidePasswordCallback is { } passwordCallback)
{
try
{
ConnectionLogger.LogTrace($"Taking password from {nameof(ProvidePasswordCallback)} delegate");
Expand All @@ -458,6 +460,7 @@ class AuthenticationCompleteException : Exception { }
{
throw new NpgsqlException($"Obtaining password using {nameof(NpgsqlConnection)}.{nameof(ProvidePasswordCallback)} delegate failed", e);
}
}

if (password is null)
password = PostgresEnvironment.Password;
Expand Down
34 changes: 18 additions & 16 deletions src/Npgsql/Internal/NpgsqlConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ internal void FlagAsWritableForMultiplexing()
/// Note that in multi-host scenarios, this references the host-specific <see cref="PoolingDataSource"/> rather than the
/// <see cref="MultiHostDataSource"/>,
/// </summary>
readonly NpgsqlDataSource _connectorSource;
readonly NpgsqlDataSource _dataSource;

internal string UserFacingConnectionString => _connectorSource.ConnectionString;
internal string UserFacingConnectionString => _dataSource.ConnectionString;

/// <summary>
/// Contains the UTC timestamp when this connector was opened, used to implement
Expand Down Expand Up @@ -315,12 +315,14 @@ internal bool PostgresCancellationPerformed

#region Constructors

internal NpgsqlConnector(NpgsqlDataSource connectorSource, NpgsqlConnection conn)
: this(connectorSource)
internal NpgsqlConnector(NpgsqlDataSource dataSource, NpgsqlConnection conn)
: this(dataSource)
{
ProvideClientCertificatesCallback = conn.ProvideClientCertificatesCallback;
UserCertificateValidationCallback = conn.UserCertificateValidationCallback;
#pragma warning disable CS0618 // Obsolete
ProvidePasswordCallback = conn.ProvidePasswordCallback;
#pragma warning restore CS0618

#pragma warning disable CA2252 // Experimental API
PhysicalOpenCallback = conn.PhysicalOpenCallback;
Expand All @@ -329,28 +331,28 @@ internal NpgsqlConnector(NpgsqlDataSource connectorSource, NpgsqlConnection conn
}

NpgsqlConnector(NpgsqlConnector connector)
: this(connector._connectorSource)
: this(connector._dataSource)
{
ProvideClientCertificatesCallback = connector.ProvideClientCertificatesCallback;
UserCertificateValidationCallback = connector.UserCertificateValidationCallback;
ProvidePasswordCallback = connector.ProvidePasswordCallback;
}

NpgsqlConnector(NpgsqlDataSource connectorSource)
NpgsqlConnector(NpgsqlDataSource dataSource)
{
Debug.Assert(connectorSource.OwnsConnectors);
Debug.Assert(dataSource.OwnsConnectors);

_connectorSource = connectorSource;
_dataSource = dataSource;

LoggingConfiguration = _connectorSource.LoggingConfiguration;
LoggingConfiguration = dataSource.LoggingConfiguration;
ConnectionLogger = LoggingConfiguration.ConnectionLogger;
CommandLogger = LoggingConfiguration.CommandLogger;
TransactionLogger = LoggingConfiguration.TransactionLogger;
CopyLogger = LoggingConfiguration.CopyLogger;

State = ConnectorState.Closed;
TransactionStatus = TransactionStatus.Idle;
Settings = connectorSource.Settings;
Settings = dataSource.Settings;
PostgresParameters = new Dictionary<string, string>();

CancelLock = new object();
Expand Down Expand Up @@ -606,7 +608,7 @@ internal async ValueTask LoadDatabaseInfo(bool forceReload, NpgsqlTimeout timeou
// multiplexing there's no connector yet). However, in the very first multiplexing connection (bootstrap phase) we create
// a connector-specific mapper, which will later become shared pool-wide one.
TypeMapper =
Settings.Multiplexing && ((MultiplexingDataSource)_connectorSource).MultiplexingTypeMapper is { } multiplexingTypeMapper
Settings.Multiplexing && ((MultiplexingDataSource)_dataSource).MultiplexingTypeMapper is { } multiplexingTypeMapper
? multiplexingTypeMapper
: new ConnectorTypeMapper(this);

Expand Down Expand Up @@ -1179,7 +1181,7 @@ async Task MultiplexingReadLoop()
SpinWait.SpinUntil(() => MultiplexAsyncWritingLock == 0 || IsBroken);

ResetReadBuffer();
_connectorSource.Return(this);
_dataSource.Return(this);
}
}

Expand Down Expand Up @@ -1216,7 +1218,7 @@ async Task MultiplexingReadLoop()
}

// "Return" the connector to the pool to for cleanup (e.g. update total connector count)
_connectorSource.Return(this);
_dataSource.Return(this);

ConnectionLogger.LogError(e, "Exception in multiplexing read loop", Id);
}
Expand Down Expand Up @@ -1923,9 +1925,9 @@ internal void Close()
}

internal bool TryRemovePendingEnlistedConnector(Transaction transaction)
=> _connectorSource.TryRemovePendingEnlistedConnector(this, transaction);
=> _dataSource.TryRemovePendingEnlistedConnector(this, transaction);

internal void Return() => _connectorSource.Return(this);
internal void Return() => _dataSource.Return(this);

/// <inheritdoc />
public void Dispose() => Close();
Expand Down Expand Up @@ -1961,7 +1963,7 @@ internal Exception Break(Exception reason)
{
ClusterStateCache.UpdateClusterState(Host, Port, ClusterState.Offline, DateTime.UtcNow,
Settings.HostRecheckSecondsTranslated);
_connectorSource.Clear();
_dataSource.Clear();
}

LogMessages.BreakingConnection(ConnectionLogger, Id, reason);
Expand Down
8 changes: 4 additions & 4 deletions src/Npgsql/MultiHostDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ sealed class MultiHostDataSource : NpgsqlDataSource

volatile int _roundRobinIndex = -1;

public MultiHostDataSource(NpgsqlConnectionStringBuilder settings, string connString, NpgsqlLoggingConfiguration loggingConfiguration)
: base(settings, connString, loggingConfiguration)
public MultiHostDataSource(NpgsqlConnectionStringBuilder settings, string connString, NpgsqlDataSourceConfiguration dataSourceConfig)
: base(settings, connString, dataSourceConfig)
{
var hosts = settings.Host!.Split(',');
_pools = new NpgsqlDataSource[hosts.Length];
Expand All @@ -40,8 +40,8 @@ public MultiHostDataSource(NpgsqlConnectionStringBuilder settings, string connSt
poolSettings.Host = host.ToString();

_pools[i] = settings.Pooling
? new PoolingDataSource(poolSettings, poolSettings.ConnectionString, loggingConfiguration, this)
: new UnpooledDataSource(poolSettings, poolSettings.ConnectionString, loggingConfiguration);
? new PoolingDataSource(poolSettings, poolSettings.ConnectionString, dataSourceConfig, this)
: new UnpooledDataSource(poolSettings, poolSettings.ConnectionString, dataSourceConfig);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Npgsql/MultiHostDataSourceWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ sealed class MultiHostDataSourceWrapper : NpgsqlDataSource
readonly MultiHostDataSource _wrappedSource;

public MultiHostDataSourceWrapper(NpgsqlConnectionStringBuilder settings, string connString, MultiHostDataSource source)
: base(settings, connString, source.LoggingConfiguration)
: base(settings, connString, source.Configuration)
=> _wrappedSource = source;

internal override (int Total, int Idle, int Busy) Statistics => _wrappedSource.Statistics;
Expand Down
8 changes: 4 additions & 4 deletions src/Npgsql/MultiplexingDataSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public bool IsBootstrapped
internal MultiplexingDataSource(
NpgsqlConnectionStringBuilder settings,
string connString,
NpgsqlLoggingConfiguration loggingConfiguration,
NpgsqlDataSourceConfiguration dataSourceConfig,
MultiHostDataSource? parentPool = null)
: base(settings, connString, loggingConfiguration, parentPool)
: base(settings, connString, dataSourceConfig, parentPool)
{
Debug.Assert(Settings.Multiplexing);

Expand All @@ -73,8 +73,8 @@ internal MultiplexingDataSource(
_multiplexCommandReader = multiplexCommandChannel.Reader;
MultiplexCommandWriter = multiplexCommandChannel.Writer;

_connectionLogger = loggingConfiguration.ConnectionLogger;
_commandLogger = loggingConfiguration.CommandLogger;
_connectionLogger = dataSourceConfig.LoggingConfiguration.ConnectionLogger;
_commandLogger = dataSourceConfig.LoggingConfiguration.CommandLogger;
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Npgsql/NpgsqlConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ public override string ConnectionString
/// that was previously opened from the pool.
/// </p>
/// </remarks>
[Obsolete("Use NpgsqlDataSource.UsePeriodicPasswordProvider or UseInlinePasswordProvider")]
public ProvidePasswordCallback? ProvidePasswordCallback { get; set; }

/// <summary>
Expand Down Expand Up @@ -1946,7 +1947,9 @@ object ICloneable.Clone()
var conn = new NpgsqlConnection(_connectionString) {
ProvideClientCertificatesCallback = ProvideClientCertificatesCallback,
UserCertificateValidationCallback = UserCertificateValidationCallback,
#pragma warning disable CS0618 // Obsolete
ProvidePasswordCallback = ProvidePasswordCallback,
#pragma warning restore CS0618
_userFacingConnectionString = _userFacingConnectionString
};
return conn;
Expand All @@ -1969,7 +1972,9 @@ public NpgsqlConnection CloneWith(string connectionString)
return new NpgsqlConnection(csb.ToString()) {
ProvideClientCertificatesCallback = ProvideClientCertificatesCallback,
UserCertificateValidationCallback = UserCertificateValidationCallback,
#pragma warning disable CS0618 // Obsolete
ProvidePasswordCallback = ProvidePasswordCallback,
#pragma warning restore CS0618
};
}

Expand Down
Loading