public VirtualConnection encryptAndWriteAsync ( long numBytes , boolean forceQueue , int timeout ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) { Tr . entry ( tc , "encryptAndWriteAsync: " + numBytes ) ; } this . asyncBytesToWrite = 0L ; this . asyncTimeout = timeout ; VirtualConnection vc = null ; try { long numBytesLeft = numBytes ; // make sure we have an output buffer of the target size ready final int packetSize = getConnLink ( ) . getPacketBufferSize ( ) ; if ( numBytesLeft > packetSize ) { getEncryptedAppBuffer ( packetSize * 2 ) ; } else { getEncryptedAppBuffer ( 1 ) ; } final int cap = this . encryptedAppBuffer . capacity ( ) ; final TCPWriteRequestContext tcp = getConnLink ( ) . getDeviceWriteInterface ( ) ; SSLEngineResult result ; int produced ; do { this . encryptedAppBuffer . clear ( ) ; result = encryptMessage ( ) ; numBytesLeft -= result . bytesConsumed ( ) ; produced = result . bytesProduced ( ) ; if ( 0 < produced ) { while ( 0 < numBytesLeft && ( cap - produced ) >= packetSize ) { // space in the current output buffer to encrypt a little more // Note: JSSE requires a full packet size of open space regardless of the input // amount, so even 100 bytes to encrypt requires 16K of output space result = encryptMessage ( ) ; numBytesLeft -= result . bytesConsumed ( ) ; produced += result . bytesProduced ( ) ; } // in case this goes async, save bytes-left to pick up later this . asyncBytesToWrite = numBytesLeft ; this . encryptedAppBuffer . flip ( ) ; tcp . setBuffer ( this . encryptedAppBuffer ) ; vc = tcp . write ( TCPWriteRequestContext . WRITE_ALL_DATA , this , forceQueue , timeout ) ; } } while ( null != vc && 0 < numBytesLeft && 0 < produced ) ; } catch ( IOException exception ) { // No FFDC needed. Callback will handle. if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "Caught exception during encryption, " + exception ) ; } this . callback . error ( getConnLink ( ) . getVirtualConnection ( ) , this , exception ) ; } catch ( Exception original ) { synchronized ( closeSync ) { // if close has been called then assume this exception was due to a race condition // with the close logic. so no FFDC here. if ( closeCalled ) { return null ; } else { throw original ; } } } if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isEntryEnabled ( ) ) { Tr . exit ( tc , "encryptAndWriteAsync: " + vc ) ; } return vc ; }
This method is called as a part of an asynchronous write but after a potential SSL handshake has taken place .