19
19
import com .mongodb .MongoInternalException ;
20
20
import com .mongodb .connection .SocketSettings ;
21
21
import com .mongodb .connection .SslSettings ;
22
+ import jdk .net .ExtendedSocketOptions ;
22
23
23
24
import javax .net .ssl .SSLParameters ;
24
25
import javax .net .ssl .SSLSocket ;
25
26
import java .io .IOException ;
27
+ import java .lang .reflect .Method ;
26
28
import java .net .InetSocketAddress ;
27
29
import java .net .Socket ;
30
+ import java .net .SocketOption ;
31
+ import java .util .Arrays ;
28
32
29
33
import static com .mongodb .internal .connection .SslHelper .enableHostNameVerification ;
30
34
import static com .mongodb .internal .connection .SslHelper .enableSni ;
31
35
import static java .util .concurrent .TimeUnit .MILLISECONDS ;
32
36
33
37
final class SocketStreamHelper {
38
+ // Keep alive options and their values for Java 11+
39
+ private static final String TCP_KEEPIDLE = "TCP_KEEPIDLE" ;
40
+ private static final int TCP_KEEPIDLE_DURATION = 300 ;
41
+ private static final String TCP_KEEPCOUNT = "TCP_KEEPCOUNT" ;
42
+ private static final int TCP_KEEPCOUNT_LIMIT = 9 ;
43
+ private static final String TCP_KEEPINTERVAL = "TCP_KEEPINTERVAL" ;
44
+ private static final int TCP_KEEPINTERVAL_DURATION = 10 ;
34
45
35
46
static void initialize (final Socket socket , final InetSocketAddress inetSocketAddress , final SocketSettings settings ,
36
47
final SslSettings sslSettings ) throws IOException {
37
48
socket .setTcpNoDelay (true );
38
49
socket .setSoTimeout (settings .getReadTimeout (MILLISECONDS ));
39
50
socket .setKeepAlive (true );
51
+
52
+ // Adding keep alive options for users of Java 11+. These options will be ignored for older Java versions.
53
+ setExtendedSocketOptions (socket );
54
+
40
55
if (settings .getReceiveBufferSize () > 0 ) {
41
56
socket .setReceiveBufferSize (settings .getReceiveBufferSize ());
42
57
}
@@ -63,6 +78,22 @@ static void initialize(final Socket socket, final InetSocketAddress inetSocketAd
63
78
socket .connect (inetSocketAddress , settings .getConnectTimeout (MILLISECONDS ));
64
79
}
65
80
81
+ @ SuppressWarnings ("unchecked" )
82
+ private static void setExtendedSocketOptions (final Socket socket ) {
83
+ if (Arrays .stream (ExtendedSocketOptions .class .getDeclaredFields ()).anyMatch (f -> f .getName ().equals (TCP_KEEPCOUNT ))) {
84
+ try {
85
+ Method setOptionMethod = Socket .class .getMethod ("setOption" , SocketOption .class , Object .class );
86
+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPCOUNT ).get (null ),
87
+ TCP_KEEPCOUNT_LIMIT );
88
+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPIDLE ).get (null ),
89
+ TCP_KEEPIDLE_DURATION );
90
+ setOptionMethod .invoke (socket , ExtendedSocketOptions .class .getDeclaredField (TCP_KEEPINTERVAL ).get (null ),
91
+ TCP_KEEPINTERVAL_DURATION );
92
+ } catch (Throwable t ) {
93
+ }
94
+ }
95
+ }
96
+
66
97
private SocketStreamHelper () {
67
98
}
68
99
}
0 commit comments