From da98067ef4d2bc52762e8f6586c876b0f8b941ae Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Thu, 16 Feb 2012 15:48:56 +0000
Subject: [PATCH] Additional fix for OPENDJ-420: Rare SSLExceptions while handling LDAPS connections and big LDAP searches
---
opends/src/server/org/opends/server/extensions/TLSByteChannel.java | 30 +++++++++++++++++++++++-------
1 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/opends/src/server/org/opends/server/extensions/TLSByteChannel.java b/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
index 9914582..1f0cf6e 100644
--- a/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
+++ b/opends/src/server/org/opends/server/extensions/TLSByteChannel.java
@@ -245,15 +245,17 @@
// Synchronize SSL unwrap with channel reads.
synchronized (unwrapLock)
{
- // Repeat if there is underflow or overflow.
+ // Read SSL packets until some unwrapped data is produced or no more
+ // data is available on the underlying channel.
boolean needRead = true;
+ int read = 0;
while (true)
{
// Read wrapped data if needed.
if (needRead)
{
recvWrappedBuffer.compact(); // Prepare for append.
- final int read = channel.read(recvWrappedBuffer);
+ read = channel.read(recvWrappedBuffer);
recvWrappedBuffer.flip(); // Restore for read.
if (read < 0)
{
@@ -288,11 +290,11 @@
break; // Retry unwrap.
case BUFFER_UNDERFLOW:
// Not enough data was read. This either means that the inbound
- // buffer was too small, or not enough data is available.
+ // buffer was too small, or not enough data was read.
final int newPktSize = sslEngine.getSession().getPacketBufferSize();
if (newPktSize > recvWrappedBuffer.capacity())
{
- // Buffer needs resizing.
+ // Increase the buffer size and reread.
final ByteBuffer newRecvWrappedBuffer = ByteBuffer
.allocate(newPktSize);
newRecvWrappedBuffer.put(recvWrappedBuffer);
@@ -300,11 +302,18 @@
recvWrappedBuffer = newRecvWrappedBuffer;
break;
}
- else
+ else if (read == 0)
{
// Not enough data is available to read a complete SSL packet.
return 0;
}
+ else
+ {
+ // The channel read may only partially fill the buffer due to
+ // buffering in the underlying channel layer, so try reading again
+ // until we are sure that we are unable to proceed.
+ break;
+ }
case CLOSED:
// Peer sent SSL close notification.
sslEngine.closeInbound();
@@ -320,7 +329,7 @@
// No application data was read, but if we are handshaking then
// try to continue.
if (result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP
- && !recvWrappedBuffer.hasRemaining())
+ && !recvWrappedBuffer.hasRemaining() && read == 0)
{
// Not enough data is available to continue handshake.
return 0;
@@ -331,11 +340,18 @@
doHandshake(true /* isReading */);
}
}
- else
+ else if (read == 0)
{
// No data available and not handshaking.
return 0;
}
+ else
+ {
+ // The channel read may only partially fill the buffer due to
+ // buffering in the underlying channel layer, so try reading again
+ // until we are sure that we are unable to proceed.
+ break;
+ }
}
}
}
--
Gitblit v1.10.0