@@ -703,7 +703,7 @@ async Task RawOpen(NpgsqlTimeout timeout, bool async, CancellationToken cancella
703703
704704 if ( Path . GetExtension ( certPath ) . ToUpperInvariant ( ) != ". PFX")
705705 {
706- #if NET5_0
706+ #if NET5_0_OR_GREATER
707707 // It's PEM time
708708 var keyPath = Settings . SslKey ?? PostgresEnvironment . SslKey ?? PostgresEnvironment . SslKeyDefault ;
709709 cert = string . IsNullOrEmpty ( password )
@@ -855,7 +855,7 @@ async Task ConnectAsync(NpgsqlTimeout timeout, CancellationToken cancellationTok
855855 // Note that there aren't any timeout-able or cancellable DNS methods
856856 var endpoints = Path. IsPathRooted( Host )
857857 ? new EndPoint [ ] { new UnixDomainSocketEndPoint ( Path . Combine ( Host , $".s.PGSQL.{Port}" ) ) }
858- : ( await Dns . GetHostAddressesAsync ( Host ) . WithCancellationAndTimeout ( timeout , cancellationToken ) )
858+ : ( await GetHostAddressesAsync ( timeout , cancellationToken ) )
859859 . Select ( a => new IPEndPoint ( a , Port ) ) . ToArray ( ) ;
860860
861861 // Give each IP an equal share of the remaining time
@@ -877,29 +877,9 @@ async Task ConnectAsync(NpgsqlTimeout timeout, CancellationToken cancellationTok
877877 ? ProtocolType. Tcp
878878 : ProtocolType. IP;
879879 var socket = new Socket ( endpoint . AddressFamily , SocketType . Stream , protocolType ) ;
880- CancellationTokenSource ? combinedCts = null ;
881880 try
882881 {
883- // .NET 5.0 added cancellation support to ConnectAsync, which allows us to implement real
884- // cancellation and timeout. On older TFMs, we fake-cancel the operation, i.e. stop waiting
885- // and raise the exception, but the actual connection task is left running.
886-
887- #if NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1
888- await socket . ConnectAsync ( endpoint )
889- . WithCancellationAndTimeout ( perIpTimeout , cancellationToken ) ;
890- #else
891- var finalCt = cancellationToken;
892-
893- if ( perIpTimeout . IsSet )
894- {
895- combinedCts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
896- combinedCts. CancelAfter ( ( int ) perIpTimeout . CheckAndGetTimeLeft ( ) . TotalMilliseconds ) ;
897- finalCt = combinedCts. Token ;
898- }
899-
900- await socket. ConnectAsync ( endpoint , finalCt ) ;
901- #endif
902-
882+ await OpenSocketConnectionAsync ( socket , endpoint , perIpTimeout , cancellationToken ) ;
903883 SetSocketOptions( socket ) ;
904884 _socket = socket;
905885 return ;
@@ -925,10 +905,41 @@ await socket.ConnectAsync(endpoint)
925905 if ( i == endpoints . Length - 1 )
926906 throw new NpgsqlException( $ "Failed to connect to { endpoint } ", e ) ;
927907 }
928- finally
929- {
930- combinedCts? . Dispose ( ) ;
931- }
908+ }
909+
910+ Task< IPAddress [ ] > GetHostAddressesAsync ( NpgsqlTimeout timeout , CancellationToken cancellationToken )
911+ {
912+ // .NET 6.0 added cancellation support to GetHostAddressesAsync, which allows us to implement real
913+ // cancellation and timeout. On older TFMs, we fake-cancel the operation, i.e. stop waiting
914+ // and raise the exception, but the actual connection task is left running.
915+
916+ #if NET6_0_OR_GREATER
917+ var task = TaskExtensions. ExecuteWithTimeout(
918+ ct => Dns . GetHostAddressesAsync ( Host , ct ) ,
919+ timeout , cancellationToken ) ;
920+ #else
921+ var task = Dns. GetHostAddressesAsync( Host) ;
922+ #endif
923+
924+ // As the cancellation support of GetHostAddressesAsync is not guaranteed on all platforms
925+ // we apply the fake-cancel mechanism in all cases.
926+ return task. WithCancellationAndTimeout( timeout, cancellationToken) ;
927+ }
928+
929+ static Task OpenSocketConnectionAsync( Socket socket , EndPoint endpoint , NpgsqlTimeout perIpTimeout , CancellationToken cancellationToken )
930+ {
931+ // .NET 5.0 added cancellation support to ConnectAsync, which allows us to implement real
932+ // cancellation and timeout. On older TFMs, we fake-cancel the operation, i.e. stop waiting
933+ // and raise the exception, but the actual connection task is left running.
934+
935+ #if NET5_0_OR_GREATER
936+ return TaskExtensions. ExecuteWithTimeout (
937+ ct => socket . ConnectAsync ( endpoint , ct ) . AsTask ( ) ,
938+ perIpTimeout , cancellationToken ) ;
939+ #else
940+ return socket. ConnectAsync ( endpoint )
941+ . WithCancellationAndTimeout ( perIpTimeout , cancellationToken ) ;
942+ #endif
932943 }
933944 }
934945
@@ -1505,15 +1516,15 @@ static RemoteCertificateValidationCallback SslRootValidation(string certRootPath
15051516
15061517 var certs = new X509Certificate2Collection ( ) ;
15071518
1508- #if NET5_0
1519+ #if NET5_0_OR_GREATER
15091520 if ( Path . GetExtension ( certRootPath ) . ToUpperInvariant ( ) != ".PFX" )
15101521 certs . ImportFromPemFile ( certRootPath ) ;
15111522#endif
15121523
15131524 if ( certs . Count == 0 )
15141525 certs . Add ( new X509Certificate2 ( certRootPath ) ) ;
15151526
1516- #if NET5_0
1527+ #if NET5_0_OR_GREATER
15171528 chain . ChainPolicy . CustomTrustStore . AddRange ( certs ) ;
15181529 chain . ChainPolicy . TrustMode = X509ChainTrustMode . CustomRootTrust ;
15191530#endif
0 commit comments