* Another workaround for 'missing algorithm' error in SSLEngine

* Made handshaking non-volatile
This commit is contained in:
Trustin Lee 2008-11-16 20:34:07 +00:00
parent 87cd22b5fd
commit 580f6f2284

View File

@ -124,8 +124,8 @@ public class SslHandler extends FrameDecoder {
private final boolean startTls; private final boolean startTls;
final Object handshakeLock = new Object(); final Object handshakeLock = new Object();
private volatile boolean needsFirstHandshake = true; private boolean initialHandshake;
private volatile boolean handshaking; private boolean handshaking;
private volatile boolean handshaken; private volatile boolean handshaken;
private volatile ChannelFuture handshakeFuture; private volatile ChannelFuture handshakeFuture;
@ -275,6 +275,7 @@ public class SslHandler extends FrameDecoder {
return this.handshakeFuture; return this.handshakeFuture;
} else { } else {
engine.beginHandshake(); engine.beginHandshake();
runDelegatedTasks();
handshakeFuture = this.handshakeFuture = newHandshakeFuture(channel); handshakeFuture = this.handshakeFuture = newHandshakeFuture(channel);
handshaking = true; handshaking = true;
} }
@ -438,11 +439,7 @@ public class SslHandler extends FrameDecoder {
SSLEngineResult result; SSLEngineResult result;
try { try {
if (handshaking || needsFirstHandshake) { synchronized (handshakeLock) {
synchronized (handshakeLock) {
result = engine.wrap(outAppBuf, outNetBuf);
}
} else {
result = engine.wrap(outAppBuf, outNetBuf); result = engine.wrap(outAppBuf, outNetBuf);
} }
} finally { } finally {
@ -504,9 +501,7 @@ public class SslHandler extends FrameDecoder {
} }
} catch (SSLException e) { } catch (SSLException e) {
success = false; success = false;
if (handshaking) { setHandshakeFailure(channel, e);
setHandshakeFailure(channel, e);
}
throw e; throw e;
} finally { } finally {
bufferPool.release(outNetBuf); bufferPool.release(outNetBuf);
@ -574,11 +569,7 @@ public class SslHandler extends FrameDecoder {
SSLEngineResult result; SSLEngineResult result;
try { try {
for (;;) { for (;;) {
if (handshaking || needsFirstHandshake) { synchronized (handshakeLock) {
synchronized (handshakeLock) {
result = engine.wrap(EMPTY_BUFFER, outNetBuf);
}
} else {
result = engine.wrap(EMPTY_BUFFER, outNetBuf); result = engine.wrap(EMPTY_BUFFER, outNetBuf);
} }
@ -600,7 +591,12 @@ public class SslHandler extends FrameDecoder {
runDelegatedTasks(); runDelegatedTasks();
break; break;
case NEED_UNWRAP: case NEED_UNWRAP:
unwrap(ctx, channel, ChannelBuffers.EMPTY_BUFFER, 0, 0); if (!Thread.holdsLock(handshakeLock)) {
// unwrap shouldn't be called when this method was
// called by unwrap - unwrap will keep running after
// this method returns.
unwrap(ctx, channel, ChannelBuffers.EMPTY_BUFFER, 0, 0);
}
break; break;
case NOT_HANDSHAKING: case NOT_HANDSHAKING:
case NEED_WRAP: case NEED_WRAP:
@ -616,9 +612,7 @@ public class SslHandler extends FrameDecoder {
} }
} }
} catch (SSLException e) { } catch (SSLException e) {
if (handshaking) { setHandshakeFailure(channel, e);
setHandshakeFailure(channel, e);
}
throw e; throw e;
} finally { } finally {
bufferPool.release(outNetBuf); bufferPool.release(outNetBuf);
@ -636,44 +630,55 @@ public class SslHandler extends FrameDecoder {
ByteBuffer outAppBuf = bufferPool.acquire(); ByteBuffer outAppBuf = bufferPool.acquire();
try { try {
boolean needsWrap = false;
loop: loop:
for (;;) { for (;;) {
SSLEngineResult result; SSLEngineResult result;
if (handshaking || needsFirstHandshake) { synchronized (handshakeLock) {
synchronized (handshakeLock) { if (initialHandshake && !engine.getUseClientMode() &&
!engine.isInboundDone() && !engine.isOutboundDone()) {
handshake(channel);
initialHandshake = false;
}
try {
result = engine.unwrap(inNetBuf, outAppBuf); result = engine.unwrap(inNetBuf, outAppBuf);
} catch (SSLException e) {
System.err.println(engine.getUseClientMode());
throw e;
} }
} else {
result = engine.unwrap(inNetBuf, outAppBuf);
}
switch (result.getHandshakeStatus()) { switch (result.getHandshakeStatus()) {
case NEED_UNWRAP: case NEED_UNWRAP:
if (inNetBuf.hasRemaining()) { if (inNetBuf.hasRemaining()) {
break;
} else {
break loop;
}
case NEED_WRAP:
wrapNonAppData(ctx, channel);
break; break;
} else { case NEED_TASK:
runDelegatedTasks();
break;
case FINISHED:
setHandshakeSuccess(channel);
needsWrap = true;
break loop; break loop;
case NOT_HANDSHAKING:
needsWrap = true;
break loop;
default:
throw new IllegalStateException(
"Unknown handshake status: " +
result.getHandshakeStatus());
} }
case NEED_WRAP:
wrapNonAppData(ctx, channel);
break;
case NEED_TASK:
runDelegatedTasks();
break;
case FINISHED:
setHandshakeSuccess(channel);
wrap(ctx, channel);
break loop;
case NOT_HANDSHAKING:
wrap(ctx, channel);
break loop;
default:
throw new IllegalStateException(
"Unknown handshake status: " +
result.getHandshakeStatus());
} }
} }
if (needsWrap) {
wrap(ctx, channel);
}
outAppBuf.flip(); outAppBuf.flip();
if (outAppBuf.hasRemaining()) { if (outAppBuf.hasRemaining()) {
@ -684,9 +689,7 @@ public class SslHandler extends FrameDecoder {
return null; return null;
} }
} catch (SSLException e) { } catch (SSLException e) {
if (handshaking) { setHandshakeFailure(channel, e);
setHandshakeFailure(channel, e);
}
throw e; throw e;
} finally { } finally {
bufferPool.release(outAppBuf); bufferPool.release(outAppBuf);
@ -694,13 +697,20 @@ public class SslHandler extends FrameDecoder {
} }
private void runDelegatedTasks() { private void runDelegatedTasks() {
Runnable task; for (;;) {
while ((task = engine.getDelegatedTask()) != null) { final Runnable task;
final Runnable t = task; synchronized (handshakeLock) {
task = engine.getDelegatedTask();
}
if (task == null) {
break;
}
delegatedTaskExecutor.execute(new Runnable() { delegatedTaskExecutor.execute(new Runnable() {
public void run() { public void run() {
synchronized (handshakeLock) { synchronized (handshakeLock) {
t.run(); task.run();
} }
} }
}); });
@ -711,7 +721,6 @@ public class SslHandler extends FrameDecoder {
synchronized (handshakeLock) { synchronized (handshakeLock) {
handshaking = false; handshaking = false;
handshaken = true; handshaken = true;
needsFirstHandshake = false; // Will not set to true again
if (handshakeFuture == null) { if (handshakeFuture == null) {
handshakeFuture = newHandshakeFuture(channel); handshakeFuture = newHandshakeFuture(channel);
@ -723,6 +732,9 @@ public class SslHandler extends FrameDecoder {
private void setHandshakeFailure(Channel channel, SSLException cause) { private void setHandshakeFailure(Channel channel, SSLException cause) {
synchronized (handshakeLock) { synchronized (handshakeLock) {
if (!handshaking) {
return;
}
handshaking = false; handshaking = false;
handshaken = false; handshaken = false;