@@ -215,6 +215,7 @@ protected void consumeDelegatedTasks() {
215215 }
216216
217217 protected void createBuffers ( SSLSession session ) {
218+ saveCryptedData (); // save any remaining data in inCrypt
218219 int netBufferMax = session .getPacketBufferSize ();
219220 int appBufferMax = Math .max (session .getApplicationBufferSize (), netBufferMax );
220221
@@ -269,6 +270,7 @@ public int write( ByteBuffer src ) throws IOException {
269270 * @return the number of bytes read.
270271 **/
271272 public int read (ByteBuffer dst ) throws IOException {
273+ tryRestoreCryptedData ();
272274 while (true ) {
273275 if (!dst .hasRemaining ())
274276 return 0 ;
@@ -329,6 +331,7 @@ private int readRemaining( ByteBuffer dst ) throws SSLException {
329331 }
330332 if ( !inData .hasRemaining () )
331333 inData .clear ();
334+ tryRestoreCryptedData ();
332335 // test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
333336 if ( inCrypt .hasRemaining () ) {
334337 unwrap ();
@@ -396,7 +399,7 @@ public void writeMore() throws IOException {
396399
397400 @ Override
398401 public boolean isNeedRead () {
399- return inData .hasRemaining () || ( inCrypt .hasRemaining () && readEngineResult .getStatus () != Status .BUFFER_UNDERFLOW && readEngineResult .getStatus () != Status .CLOSED );
402+ return saveCryptData != null || inData .hasRemaining () || ( inCrypt .hasRemaining () && readEngineResult .getStatus () != Status .BUFFER_UNDERFLOW && readEngineResult .getStatus () != Status .CLOSED );
400403 }
401404
402405 @ Override
@@ -430,4 +433,31 @@ public boolean isBlocking() {
430433 public SSLEngine getSSLEngine () {
431434 return sslEngine ;
432435 }
436+
437+
438+ // to avoid complexities with inCrypt, extra unwrapped data after SSL handshake will be saved off in a byte array
439+ // and the inserted back on first read
440+ private byte [] saveCryptData = null ;
441+ private void saveCryptedData ()
442+ {
443+ // did we find any extra data?
444+ if (inCrypt != null && inCrypt .remaining () > 0 )
445+ {
446+ int saveCryptSize = inCrypt .remaining ();
447+ saveCryptData = new byte [saveCryptSize ];
448+ inCrypt .get (saveCryptData );
449+ }
450+ }
451+
452+ private void tryRestoreCryptedData ()
453+ {
454+ // was there any extra data, then put into inCrypt and clean up
455+ if ( saveCryptData != null )
456+ {
457+ inCrypt .clear ();
458+ inCrypt .put ( saveCryptData );
459+ inCrypt .flip ();
460+ saveCryptData = null ;
461+ }
462+ }
433463}
0 commit comments