@@ -102,20 +102,75 @@ public class WolfSSLSession {
102102 /**
103103 * Creates a new SSL/TLS session.
104104 *
105+ * Native session created also creates JNI SSLAppData for usage
106+ * internal to wolfSSL JNI. This constructor creates a default
107+ * pipe() to use for interrupting threads waiting in select()/poll()
108+ * when close() is called. To skip creation of this pipe() use
109+ * the WolfSSLSession(WolfSSLContext ctx, boolean setupIOPipe)
110+ * constructor with 'setupIOPipe' set to false.
111+ *
105112 * @param ctx WolfSSLContext object used to create SSL session.
106113 *
107114 * @throws com.wolfssl.WolfSSLException if session object creation
108115 * failed.
109116 */
110117 public WolfSSLSession (WolfSSLContext ctx ) throws WolfSSLException {
111118
112- sslPtr = newSSL (ctx .getContextPtr ());
119+ sslPtr = newSSL (ctx .getContextPtr (), true );
113120 if (sslPtr == 0 ) {
114121 throw new WolfSSLException ("Failed to create SSL Object" );
115122 }
116123
117124 WolfSSLDebug .log (getClass (), WolfSSLDebug .Component .JNI ,
118- WolfSSLDebug .INFO , sslPtr , "creating new WolfSSLSession" );
125+ WolfSSLDebug .INFO , sslPtr ,
126+ "creating new WolfSSLSession (with I/O pipe)" );
127+
128+ synchronized (stateLock ) {
129+ this .active = true ;
130+ }
131+
132+ /* save context reference for I/O callbacks from JNI */
133+ this .ctx = ctx ;
134+ }
135+
136+ /**
137+ * Creates a new SSL/TLS session.
138+ *
139+ * Native session created also creates JNI SSLAppData for usage
140+ * internal to wolfSSL JNI. A pipe() can be created internally to wolfSSL
141+ * JNI to use for interrupting threads waiting in select()/poll()
142+ * when close() is called. To skip creation of this pipe(), set
143+ * 'setupIOPipe' to false.
144+ *
145+ * It is generally recommended to have wolfSSL JNI create the native
146+ * pipe(), unless you will be operating over non-Socket I/O. For example,
147+ * when this WolfSSLSession is being created from the JSSE level
148+ * SSLEngine class.
149+ *
150+ * @param ctx WolfSSLContext object used to create SSL session.
151+ * @param setupIOPipe true to create internal IO pipe(), otherwise
152+ * false
153+ *
154+ * @throws com.wolfssl.WolfSSLException if session object creation
155+ * failed.
156+ */
157+ public WolfSSLSession (WolfSSLContext ctx , boolean setupIOPipe )
158+ throws WolfSSLException {
159+
160+ sslPtr = newSSL (ctx .getContextPtr (), false );
161+ if (sslPtr == 0 ) {
162+ throw new WolfSSLException ("Failed to create SSL Object" );
163+ }
164+
165+ if (setupIOPipe ) {
166+ WolfSSLDebug .log (getClass (), WolfSSLDebug .Component .JNI ,
167+ WolfSSLDebug .INFO , sslPtr ,
168+ "creating new WolfSSLSession (with I/O pipe)" );
169+ } else {
170+ WolfSSLDebug .log (getClass (), WolfSSLDebug .Component .JNI ,
171+ WolfSSLDebug .INFO , sslPtr ,
172+ "creating new WolfSSLSession (without I/O pipe)" );
173+ }
119174
120175 synchronized (stateLock ) {
121176 this .active = true ;
@@ -240,7 +295,7 @@ private synchronized void confirmObjectIsActive()
240295
241296 /* ------------------ native method declarations -------------------- */
242297
243- private native long newSSL (long ctx );
298+ private native long newSSL (long ctx , boolean withIOPipe );
244299 private native int setFd (long ssl , Socket sd , int type );
245300 private native int setFd (long ssl , DatagramSocket sd , int type );
246301 private native int useCertificateFile (long ssl , String file , int format );
@@ -357,6 +412,8 @@ private native int setTlsHmacInner(long ssl, byte[] inner, long sz,
357412 private native int set1SigAlgsList (long ssl , String list );
358413 private native int useSupportedCurve (long ssl , int name );
359414 private native int hasTicket (long session );
415+ private native int interruptBlockedIO (long ssl );
416+ private native int getThreadsBlockedInPoll (long ssl );
360417
361418 /* ------------------- session-specific methods --------------------- */
362419
@@ -4125,6 +4182,49 @@ public synchronized void setIOSend(WolfSSLIOSendCallback callback)
41254182 }
41264183 }
41274184
4185+ /**
4186+ * Interrupt native I/O operations blocked inside select()/poll().
4187+ *
4188+ * This is used by wolfJSSE when SSLSocket.close() is called, to wake up
4189+ * threads that are blocked in select()/poll().
4190+ *
4191+ * @return WolfSSL.SSL_SUCCESS on success, negative on error.
4192+ *
4193+ * @throws IllegalStateException WolfSSLSession has been freed
4194+ */
4195+ public synchronized int interruptBlockedIO ()
4196+ throws IllegalStateException {
4197+
4198+ confirmObjectIsActive ();
4199+
4200+ /* Not synchronizing on sslLock, since we want to interrupt threads
4201+ * blocked on I/O operations, which will already hold sslLock */
4202+
4203+ WolfSSLDebug .log (getClass (), WolfSSLDebug .Component .JNI ,
4204+ WolfSSLDebug .INFO , "entered interruptBlockedIO()" );
4205+
4206+ return interruptBlockedIO (this .sslPtr );
4207+ }
4208+
4209+ /**
4210+ * Get count of threads currently blocked in select() or poll()
4211+ * at the native JNI level.
4212+ *
4213+ * @return count of threads waiting in select() or poll()
4214+ *
4215+ * @throws IllegalStateException WolfSSLSession has been freed
4216+ */
4217+ public synchronized int getThreadsBlockedInPoll ()
4218+ throws IllegalStateException {
4219+
4220+ confirmObjectIsActive ();
4221+
4222+ WolfSSLDebug .log (getClass (), WolfSSLDebug .Component .JNI ,
4223+ WolfSSLDebug .INFO , "entered getThreadsBlockedInPoll()" );
4224+
4225+ return getThreadsBlockedInPoll (this .sslPtr );
4226+ }
4227+
41284228 /**
41294229 * Use SNI name with this session.
41304230 *
0 commit comments