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 ;
23
22
24
23
import javax .net .ssl .SSLParameters ;
25
24
import javax .net .ssl .SSLSocket ;
26
25
import java .io .IOException ;
26
+ import java .lang .reflect .InvocationTargetException ;
27
27
import java .lang .reflect .Method ;
28
28
import java .net .InetSocketAddress ;
29
29
import java .net .Socket ;
30
30
import java .net .SocketOption ;
31
- import java .util .Arrays ;
32
31
33
32
import static com .mongodb .internal .connection .SslHelper .enableHostNameVerification ;
34
33
import static com .mongodb .internal .connection .SslHelper .enableSni ;
35
34
import static java .util .concurrent .TimeUnit .MILLISECONDS ;
36
35
36
+ @ SuppressWarnings ({"unchecked" , "rawtypes" })
37
37
final class SocketStreamHelper {
38
38
// Keep alive options and their values for Java 11+
39
39
private static final String TCP_KEEPIDLE = "TCP_KEEPIDLE" ;
@@ -43,6 +43,35 @@ final class SocketStreamHelper {
43
43
private static final String TCP_KEEPINTERVAL = "TCP_KEEPINTERVAL" ;
44
44
private static final int TCP_KEEPINTERVAL_DURATION = 10 ;
45
45
46
+ private static final SocketOption <Integer > KEEP_COUNT_OPTION ;
47
+ private static final SocketOption <Integer > KEEP_IDLE_OPTION ;
48
+ private static final SocketOption <Integer > KEEP_INTERVAL_OPTION ;
49
+
50
+ private static final Method SET_OPTION_METHOD ;
51
+
52
+ static {
53
+ SocketOption <Integer > keepCountOption = null ;
54
+ SocketOption <Integer > keepIdleOption = null ;
55
+ SocketOption <Integer > keepIntervalOption = null ;
56
+ Method setOptionMethod = null ;
57
+
58
+ try {
59
+ setOptionMethod = Socket .class .getMethod ("setOption" , SocketOption .class , Object .class );
60
+
61
+ Class extendedSocketOptionsClass = Class .forName ("jdk.net.ExtendedSocketOptions" );
62
+ keepCountOption = (SocketOption <Integer >) extendedSocketOptionsClass .getDeclaredField (TCP_KEEPCOUNT ).get (null );
63
+ keepIdleOption = (SocketOption <Integer >) extendedSocketOptionsClass .getDeclaredField (TCP_KEEPIDLE ).get (null );
64
+ keepIntervalOption = (SocketOption <Integer >) extendedSocketOptionsClass .getDeclaredField (TCP_KEEPINTERVAL ).get (null );
65
+ } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | IllegalAccessException e ) {
66
+ // ignore: this is expected on JDKs < 11 and some deployments that don't include the jdk.net package
67
+ }
68
+
69
+ KEEP_COUNT_OPTION = keepCountOption ;
70
+ KEEP_IDLE_OPTION = keepIdleOption ;
71
+ KEEP_INTERVAL_OPTION = keepIntervalOption ;
72
+ SET_OPTION_METHOD = setOptionMethod ;
73
+ }
74
+
46
75
static void initialize (final Socket socket , final InetSocketAddress inetSocketAddress , final SocketSettings settings ,
47
76
final SslSettings sslSettings ) throws IOException {
48
77
socket .setTcpNoDelay (true );
@@ -78,19 +107,21 @@ static void initialize(final Socket socket, final InetSocketAddress inetSocketAd
78
107
socket .connect (inetSocketAddress , settings .getConnectTimeout (MILLISECONDS ));
79
108
}
80
109
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 ) {
110
+ static void setExtendedSocketOptions ( final Socket socket ) {
111
+ try {
112
+ if (SET_OPTION_METHOD != null ) {
113
+ if ( KEEP_COUNT_OPTION != null ) {
114
+ SET_OPTION_METHOD . invoke ( socket , KEEP_COUNT_OPTION , TCP_KEEPCOUNT_LIMIT );
115
+ }
116
+ if ( KEEP_IDLE_OPTION != null ) {
117
+ SET_OPTION_METHOD .invoke (socket , KEEP_IDLE_OPTION , TCP_KEEPIDLE_DURATION );
118
+ }
119
+ if ( KEEP_INTERVAL_OPTION != null ) {
120
+ SET_OPTION_METHOD . invoke ( socket , KEEP_INTERVAL_OPTION , TCP_KEEPINTERVAL_DURATION );
121
+ }
93
122
}
123
+ } catch (IllegalAccessException | InvocationTargetException e ) {
124
+ // ignore failures, as this is best effort
94
125
}
95
126
}
96
127
0 commit comments