Skip to content

Commit 552b341

Browse files
authored
Merge pull request #395 from zhenlineo/1.5-tls
Added an exception for Closed status in unwrap(write) method
2 parents dfc1e77 + b950769 commit 552b341

File tree

1 file changed

+92
-73
lines changed

1 file changed

+92
-73
lines changed

driver/src/main/java/org/neo4j/driver/internal/security/TLSSocketChannel.java

Lines changed: 92 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,11 @@ private void runHandshake() throws IOException
133133
handshakeStatus = runDelegatedTasks();
134134
break;
135135
case NEED_UNWRAP:
136-
// Unwrap the ssl packet to value ssl handshake information
136+
// Unwrap the ssl packet to obtain ssl handshake status. The content of the message is not needed.
137137
handshakeStatus = unwrap( DUMMY_BUFFER );
138138
break;
139139
case NEED_WRAP:
140-
// Wrap the app packet into an ssl packet to add ssl handshake information
140+
// Wrap the app packet into an ssl packet to send ssl handshake to server
141141
handshakeStatus = wrap( plainOut );
142142
break;
143143
}
@@ -248,7 +248,7 @@ private HandshakeStatus unwrap( ByteBuffer buffer ) throws IOException
248248
/* In normal situations, enlarging buffers should happen very very rarely, as usually,
249249
the initial size for application buffer and network buffer is greater than 1024 * 10,
250250
and by using ChunkedInput and ChunkedOutput, the chunks are limited to 8192.
251-
So we should not value any enlarging buffer request in most cases. */
251+
So we should not have any buffer enlarging request in most cases. */
252252
switch ( status )
253253
{
254254
case OK:
@@ -258,54 +258,20 @@ private HandshakeStatus unwrap( ByteBuffer buffer ) throws IOException
258258
handshakeStatus = runDelegatedTasks();
259259
break;
260260
case BUFFER_OVERFLOW:
261-
plainIn.flip();
262-
// Could attempt to drain the plainIn buffer of any already obtained
263-
// data, but we'll just increase it to the size needed.
264-
int curAppSize = plainIn.capacity();
265-
int appSize = sslEngine.getSession().getApplicationBufferSize();
266-
int newAppSize = appSize + plainIn.remaining();
267-
if ( newAppSize > appSize * 2 )
268-
{
269-
throw new ClientException(
270-
format( "Failed ro enlarge application input buffer from %s to %s, as the maximum " +
271-
"buffer size allowed is %s. The content in the buffer is: %s\n",
272-
curAppSize, newAppSize, appSize * 2, BytePrinter.hex( plainIn ) ) );
273-
}
274-
ByteBuffer newPlainIn = ByteBuffer.allocate( newAppSize );
275-
newPlainIn.put( plainIn );
276-
plainIn = newPlainIn;
277-
logger.debug( "Enlarged application input buffer from %s to %s. " +
278-
"This operation should be a rare operation.", curAppSize, newAppSize );
279-
// retry the operation.
280-
break;
261+
enlargeApplicationInputBuffer();
262+
break; // retry the operation.
281263
case BUFFER_UNDERFLOW:
282-
int curNetSize = cipherIn.capacity();
283-
int netSize = sslEngine.getSession().getPacketBufferSize();
284-
// Resize buffer if needed.
285-
if ( netSize > curNetSize )
286-
{
287-
ByteBuffer newCipherIn = ByteBuffer.allocate( netSize );
288-
newCipherIn.put( cipherIn );
289-
cipherIn = newCipherIn;
290-
logger.debug( "Enlarged network input buffer from %s to %s. " +
291-
"This operation should be a rare operation.", curNetSize, netSize );
292-
}
293-
else
294-
{
295-
// Otherwise, make room for reading more data from channel
296-
cipherIn.compact();
297-
}
298-
return handshakeStatus; // old status
264+
enlargeNetworkInputBuffer();
265+
return handshakeStatus; // return directly and require read more bytes from network channel to continue
299266
case CLOSED:
300267
// RFC 2246 #7.2.1 requires us to stop accepting input.
301268
sslEngine.closeInbound();
302269
break;
303270
default:
304-
throw new ClientException( "Got unexpected status " + status + ", " + unwrapResult );
271+
throw new ClientException( "Got unexpected status " + status + " while reading encrypted data.");
305272
}
306273
}
307-
while ( cipherIn.hasRemaining() ); /* Remember we are doing blocking reading.
308-
We expect we should first handle all the data we've got and then decide what to do next. */
274+
while ( cipherIn.hasRemaining() );
309275

310276
cipherIn.compact();
311277
return handshakeStatus;
@@ -339,38 +305,13 @@ private HandshakeStatus wrap( ByteBuffer buffer ) throws IOException, ClientExce
339305
cipherOut.clear();
340306
break;
341307
case BUFFER_OVERFLOW:
342-
// Enlarge the buffer and return the old status
343-
int curNetSize = cipherOut.capacity();
344-
int netSize = sslEngine.getSession().getPacketBufferSize();
345-
if ( netSize > curNetSize )
346-
{
347-
// enlarge the peer application data buffer
348-
cipherOut = ByteBuffer.allocate( netSize );
349-
logger.debug( "Enlarged network output buffer from %s to %s. " +
350-
"This operation should be a rare operation.", curNetSize, netSize );
351-
}
352-
else
353-
{
354-
logger.debug( "Network output buffer doesn't need enlarging, flushing data to the channel instead to open up space on the buffer." );
355-
// flush as much data as possible
356-
cipherOut.flip();
357-
while ( cipherOut.hasRemaining() ) {
358-
int written = channelWrite( cipherOut );
359-
360-
if (written > 0) {
361-
break;
362-
}
363-
364-
logger.debug( "having difficulty flushing data (network contention on local computer?). will continue trying after yielding execution." );
365-
Thread.yield();
366-
367-
logger.debug( "nothing written to the underlying channel (network output buffer is full?), will try till we can." );
368-
}
369-
cipherOut.compact();
370-
}
308+
enlargeNetworkOutBuffer();
371309
break;
310+
case CLOSED:
311+
sslEngine.closeOutbound();
312+
throw new ServiceUnavailableException( "Encrypted connection closed while writing encrypted data." );
372313
default:
373-
throw new ClientException( "Got unexpected status " + status );
314+
throw new ClientException( "Got unexpected status " + status + " while writing encrypted data." );
374315
}
375316
return handshakeStatus;
376317
}
@@ -407,7 +348,10 @@ private static int bufferCopy( ByteBuffer from, ByteBuffer to )
407348
return maxTransfer;
408349
}
409350

351+
410352
@Override
353+
// try to read and return how many bytes have been read
354+
// throw exception when failed to continue read more while expecting more to read
411355
public int read( ByteBuffer dst ) throws IOException
412356
{
413357
/**
@@ -488,6 +432,81 @@ public void close() throws IOException
488432
}
489433
}
490434

435+
private void enlargeNetworkInputBuffer()
436+
{
437+
int curNetSize = cipherIn.capacity();
438+
int netSize = sslEngine.getSession().getPacketBufferSize();
439+
// Resize buffer if needed.
440+
if ( netSize > curNetSize )
441+
{
442+
ByteBuffer newCipherIn = ByteBuffer.allocate( netSize );
443+
newCipherIn.put( cipherIn );
444+
cipherIn = newCipherIn;
445+
logger.debug( "Enlarged network input buffer from %s to %s. " +
446+
"This operation should be a rare operation.", curNetSize, netSize );
447+
}
448+
else
449+
{
450+
// Otherwise, make room for reading more data from channel
451+
cipherIn.compact();
452+
}
453+
}
454+
455+
private void enlargeApplicationInputBuffer()
456+
{
457+
plainIn.flip();
458+
// Could attempt to drain the plainIn buffer of any already obtained
459+
// data, but we'll just increase it to the size needed.
460+
int curAppSize = plainIn.capacity();
461+
int appSize = sslEngine.getSession().getApplicationBufferSize();
462+
int newAppSize = appSize + plainIn.remaining();
463+
if ( newAppSize > appSize * 2 )
464+
{
465+
throw new ClientException(
466+
format( "Failed ro enlarge application input buffer from %s to %s, as the maximum " +
467+
"buffer size allowed is %s. The content in the buffer is: %s\n",
468+
curAppSize, newAppSize, appSize * 2, BytePrinter.hex( plainIn ) ) );
469+
}
470+
ByteBuffer newPlainIn = ByteBuffer.allocate( newAppSize );
471+
newPlainIn.put( plainIn );
472+
plainIn = newPlainIn;
473+
logger.debug( "Enlarged application input buffer from %s to %s. " +
474+
"This operation should be a rare operation.", curAppSize, newAppSize );
475+
}
476+
477+
private void enlargeNetworkOutBuffer() throws IOException
478+
{
479+
// Enlarge the buffer and return the old status
480+
int curNetSize = cipherOut.capacity();
481+
int netSize = sslEngine.getSession().getPacketBufferSize();
482+
if ( netSize > curNetSize )
483+
{
484+
// enlarge the peer application data buffer
485+
cipherOut = ByteBuffer.allocate( netSize );
486+
logger.debug( "Enlarged network output buffer from %s to %s. " +
487+
"This operation should be a rare operation.", curNetSize, netSize );
488+
}
489+
else
490+
{
491+
logger.debug( "Network output buffer doesn't need enlarging, flushing data to the channel instead to open up space on the buffer." );
492+
// flush as much data as possible
493+
cipherOut.flip();
494+
while ( cipherOut.hasRemaining() ) {
495+
int written = channelWrite( cipherOut );
496+
497+
if (written > 0) {
498+
break;
499+
}
500+
501+
logger.debug( "having difficulty flushing data (network contention on local computer?). will continue trying after yielding execution." );
502+
Thread.yield();
503+
504+
logger.debug( "nothing written to the underlying channel (network output buffer is full?), will try till we can." );
505+
}
506+
cipherOut.compact();
507+
}
508+
}
509+
491510
@Override
492511
public String toString()
493512
{

0 commit comments

Comments
 (0)