@@ -150,6 +150,7 @@ private static CallSite callSite(final CallSite[] sites, final CallSiteIndex ind
150150 private final ByteBuffer dummy = ByteBuffer .allocate (0 ); // could be static
151151
152152 private boolean initialHandshake = false ;
153+ private transient long initializeTime ;
153154
154155 private SSLEngineResult .HandshakeStatus handshakeStatus ; // != null after hand-shake starts
155156 private SSLEngineResult .Status status ;
@@ -178,6 +179,9 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
178179 set_sync (context , runtime .getTrue ()); // io.sync = true
179180 setInstanceVariable ("@sync_close" , runtime .getFalse ()); // self.sync_close = false
180181 sslContext .setup (context );
182+
183+ this .initializeTime = System .currentTimeMillis ();
184+
181185 return Utils .invokeSuper (context , this , args , Block .NULL_BLOCK ); // super()
182186 }
183187
@@ -199,6 +203,8 @@ private IRubyObject fallback_set_io_nonblock_checked(ThreadContext context, Ruby
199203 return context .nil ;
200204 }
201205
206+ private static final String SESSION_SOCKET_ID = "socket_id" ;
207+
202208 private SSLEngine ossl_ssl_setup (final ThreadContext context , final boolean server ) {
203209 SSLEngine engine = this .engine ;
204210 if ( engine != null ) return engine ;
@@ -651,6 +657,11 @@ private int writeToChannel(ByteBuffer buffer, boolean blocking) throws IOExcepti
651657
652658 private void finishInitialHandshake () {
653659 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+ }
654665 }
655666
656667 private void callRenegotiationCallback (final ThreadContext context ) throws RaiseException {
@@ -1137,7 +1148,7 @@ private boolean reusableSSLEngine() {
11371148 if ( engine != null ) {
11381149 final String peerHost = engine .getPeerHost ();
11391150 if ( peerHost != null && peerHost .length () > 0 ) {
1140- // NOT getSSLContext().createSSLEngine() - no hints for session reuse
1151+ // getSSLContext().createSSLEngine() - no hints for session reuse
11411152 return true ;
11421153 }
11431154 }
@@ -1146,14 +1157,23 @@ private boolean reusableSSLEngine() {
11461157
11471158 @ JRubyMethod (name = "session_reused?" )
11481159 public IRubyObject session_reused_p () {
1149- if ( reusableSSLEngine () ) {
1150- if ( ! engine .getEnableSessionCreation () ) {
1160+ if (reusableSSLEngine ()) {
1161+ if (! engine .getEnableSessionCreation ()) {
11511162 // if session creation is disabled we can be sure its to be re-used
11521163 return getRuntime ().getTrue ();
11531164 }
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+ }
11551176 }
1156- //warn(getRuntime().getCurrentContext(), "WARNING: SSLSocket#session_reused? is not supported");
11571177 return getRuntime ().getNil (); // can not decide - probably not
11581178 }
11591179
@@ -1163,6 +1183,10 @@ final javax.net.ssl.SSLSession sslSession() {
11631183 return engine == null ? null : engine .getSession ();
11641184 }
11651185
1186+ static boolean isNullSession (final javax .net .ssl .SSLSession session ) {
1187+ return session == null || "SSL_NULL_WITH_NULL_NULL" .equals (session .getCipherSuite ());
1188+ }
1189+
11661190 private transient SSLSession session ;
11671191
11681192 @ JRubyMethod (name = "session" )
0 commit comments