diff --git a/README.md b/README.md index 46dbfd180d..8263f5a1fc 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ In addition to the standard connection parameters the driver supports a number o | loginTimeout | Integer | 0 | Specify how long to wait for establishment of a database connection.| | connectTimeout | Integer | 10 | The timeout value used for socket connect operations. | | socketTimeout | Integer | 0 | The timeout value used for socket read operations. | +| sslResponseTimeout | Integer | 5000 | Socket timeout waiting for a response from a request for SSL upgrade from the server. | | tcpKeepAlive | Boolean | false | Enable or disable TCP keep-alive. | | tcpNoDelay | Boolean | true | Enable or disable TCP no delay. | | ApplicationName | String | PostgreSQL JDBC Driver | The application name (require server version >= 9.0). If assumeMinServerVersion is set to >= 9.0 this will be sent in the startup packets, otherwise after the connection is made | diff --git a/docs/documentation/head/connect.md b/docs/documentation/head/connect.md index c1eb81ffb0..4ae093a8f7 100644 --- a/docs/documentation/head/connect.md +++ b/docs/documentation/head/connect.md @@ -327,6 +327,10 @@ Connection conn = DriverManager.getConnection(url); detecting network problems. The timeout is specified in seconds and a value of zero means that it is disabled. +* **sslResponseTimeout** = int + The timeout value in milliseconds that we wait for a response from the server + after requesting the connection be upgraded to SSL. + * **cancelSignalTimeout** = int Cancel command is sent out of band over its own connection, so cancel message can itself get diff --git a/pgjdbc/src/main/java/org/postgresql/PGProperty.java b/pgjdbc/src/main/java/org/postgresql/PGProperty.java index b683e68c37..d7851d4271 100644 --- a/pgjdbc/src/main/java/org/postgresql/PGProperty.java +++ b/pgjdbc/src/main/java/org/postgresql/PGProperty.java @@ -672,6 +672,15 @@ public enum PGProperty { null, "A class, implementing javax.security.auth.callback.CallbackHandler that can handle PassworCallback for the ssl password."), + /** + *

After requesting an upgrade to SSL from the server there are reports of the server not responding due to a failover + * without a timeout here, the client can wait forever. This timeout will be set before the request and reset after

+ */ + SSL_RESPONSE_TIMEOUT( + "sslResponseTimeout", + "5000", + "Time in milliseconds we wait for a response from the server after requesting SSL upgrade"), + /** * File containing the root certificate when validating server ({@code sslmode} = {@code * verify-ca} or {@code verify-full}). Default will be the file {@code root.crt} in {@code diff --git a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java index 0e10796863..6ef64db941 100644 --- a/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java +++ b/pgjdbc/src/main/java/org/postgresql/core/v3/ConnectionFactoryImpl.java @@ -532,6 +532,17 @@ private PGStream enableSSL(PGStream pgStream, SslMode sslMode, Properties info, LOGGER.log(Level.FINEST, " FE=> SSLRequest"); + int sslTimeout = PGProperty.SSL_RESPONSE_TIMEOUT.getInt(info); + int currentTimeout = pgStream.getSocket().getSoTimeout(); + + // if the current timeout is less than sslTimeout then + // use the smaller timeout. We could do something tricky + // here to not set it in that case but this is pretty readable + if (currentTimeout > 0 && currentTimeout < sslTimeout) { + sslTimeout = currentTimeout; + } + + pgStream.getSocket().setSoTimeout(sslTimeout); // Send SSL request packet pgStream.sendInteger4(8); pgStream.sendInteger2(1234); @@ -540,6 +551,8 @@ private PGStream enableSSL(PGStream pgStream, SslMode sslMode, Properties info, // Now get the response from the backend, one of N, E, S. int beresp = pgStream.receiveChar(); + pgStream.getSocket().setSoTimeout(currentTimeout); + switch (beresp) { case 'E': LOGGER.log(Level.FINEST, " <=BE SSLError"); diff --git a/pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java b/pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java index 8fc68cd926..4a75fdc736 100644 --- a/pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java +++ b/pgjdbc/src/main/java/org/postgresql/ds/common/BaseDataSource.java @@ -354,6 +354,24 @@ public void setConnectTimeout(int connectTimeout) { PGProperty.CONNECT_TIMEOUT.set(properties, connectTimeout); } + /** + * + * @return SSL ResponseTimeout + * @see PGProperty#SSL_RESPONSE_TIMEOUT + */ + public int getSslResponseTimeout() { + return PGProperty.SSL_RESPONSE_TIMEOUT.getIntNoCheck(properties); + } + + /** + * + * @param sslResponseTimeout ssl response timeout + * @see PGProperty#SSL_RESPONSE_TIMEOUT + */ + public void setSslResponseTimeout(int sslResponseTimeout) { + PGProperty.SSL_RESPONSE_TIMEOUT.set(properties,sslResponseTimeout); + } + /** * @return protocol version * @see PGProperty#PROTOCOL_VERSION