@@ -150,6 +150,7 @@ private static CallSite callSite(final CallSite[] sites, final CallSiteIndex ind
150
150
private final ByteBuffer dummy = ByteBuffer .allocate (0 ); // could be static
151
151
152
152
private boolean initialHandshake = false ;
153
+ private transient long initializeTime ;
153
154
154
155
private SSLEngineResult .HandshakeStatus handshakeStatus ; // != null after hand-shake starts
155
156
private SSLEngineResult .Status status ;
@@ -178,6 +179,9 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
178
179
set_sync (context , runtime .getTrue ()); // io.sync = true
179
180
setInstanceVariable ("@sync_close" , runtime .getFalse ()); // self.sync_close = false
180
181
sslContext .setup (context );
182
+
183
+ this .initializeTime = System .currentTimeMillis ();
184
+
181
185
return Utils .invokeSuper (context , this , args , Block .NULL_BLOCK ); // super()
182
186
}
183
187
@@ -199,6 +203,8 @@ private IRubyObject fallback_set_io_nonblock_checked(ThreadContext context, Ruby
199
203
return context .nil ;
200
204
}
201
205
206
+ private static final String SESSION_SOCKET_ID = "socket_id" ;
207
+
202
208
private SSLEngine ossl_ssl_setup (final ThreadContext context , final boolean server ) {
203
209
SSLEngine engine = this .engine ;
204
210
if ( engine != null ) return engine ;
@@ -651,6 +657,11 @@ private int writeToChannel(ByteBuffer buffer, boolean blocking) throws IOExcepti
651
657
652
658
private void finishInitialHandshake () {
653
659
initialHandshake = false ;
660
+
661
+ final javax .net .ssl .SSLSession session = engine .getSession ();
662
+ if (session .getValue (SESSION_SOCKET_ID ) != null ) {
663
+ session .putValue (SESSION_SOCKET_ID , getObjectId ());
664
+ }
654
665
}
655
666
656
667
private void callRenegotiationCallback (final ThreadContext context ) throws RaiseException {
@@ -1137,7 +1148,7 @@ private boolean reusableSSLEngine() {
1137
1148
if ( engine != null ) {
1138
1149
final String peerHost = engine .getPeerHost ();
1139
1150
if ( peerHost != null && peerHost .length () > 0 ) {
1140
- // NOT getSSLContext().createSSLEngine() - no hints for session reuse
1151
+ // getSSLContext().createSSLEngine() - no hints for session reuse
1141
1152
return true ;
1142
1153
}
1143
1154
}
@@ -1146,14 +1157,23 @@ private boolean reusableSSLEngine() {
1146
1157
1147
1158
@ JRubyMethod (name = "session_reused?" )
1148
1159
public IRubyObject session_reused_p () {
1149
- if ( reusableSSLEngine () ) {
1150
- if ( ! engine .getEnableSessionCreation () ) {
1160
+ if (reusableSSLEngine ()) {
1161
+ if (! engine .getEnableSessionCreation ()) {
1151
1162
// if session creation is disabled we can be sure its to be re-used
1152
1163
return getRuntime ().getTrue ();
1153
1164
}
1154
- //return getRuntime().getFalse(); // NOTE: likely incorrect (we can not decide)
1165
+ // return getRuntime().getFalse(); // incorrect (we can not decide)
1166
+ }
1167
+ javax .net .ssl .SSLSession session = sslSession ();
1168
+ if (!isNullSession (session )) {
1169
+ if (session .getCreationTime () < this .initializeTime ) {
1170
+ return getRuntime ().getTrue ();
1171
+ }
1172
+ Object socketId = session .getValue (SESSION_SOCKET_ID );
1173
+ if (socketId != null && ((Long ) socketId ).longValue () != getObjectId ()) {
1174
+ return getRuntime ().getTrue ();
1175
+ }
1155
1176
}
1156
- //warn(getRuntime().getCurrentContext(), "WARNING: SSLSocket#session_reused? is not supported");
1157
1177
return getRuntime ().getNil (); // can not decide - probably not
1158
1178
}
1159
1179
@@ -1163,6 +1183,10 @@ final javax.net.ssl.SSLSession sslSession() {
1163
1183
return engine == null ? null : engine .getSession ();
1164
1184
}
1165
1185
1186
+ static boolean isNullSession (final javax .net .ssl .SSLSession session ) {
1187
+ return session == null || "SSL_NULL_WITH_NULL_NULL" .equals (session .getCipherSuite ());
1188
+ }
1189
+
1166
1190
private transient SSLSession session ;
1167
1191
1168
1192
@ JRubyMethod (name = "session" )
0 commit comments