X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Fio%2Fssl%2FSslConnection.java;h=c68cc06c48f1c40ea0b7f634d2cf3cefaf18b3e1;hp=ee9e449b15110bd5e613ca531cda3e2d2600bc8e;hb=ba4f228fa9f72d50991a2218cfd83987ef5d385e;hpb=875b5e9651498a0cd8e0001c0742ba843e47cad0 diff --git a/lib/jetty/org/eclipse/jetty/io/ssl/SslConnection.java b/lib/jetty/org/eclipse/jetty/io/ssl/SslConnection.java index ee9e449b..c68cc06c 100644 --- a/lib/jetty/org/eclipse/jetty/io/ssl/SslConnection.java +++ b/lib/jetty/org/eclipse/jetty/io/ssl/SslConnection.java @@ -1,6 +1,6 @@ // // ======================================================================== -// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 @@ -305,7 +305,7 @@ public class SslConnection extends AbstractConnection { @Override public void succeeded() - { + { } @Override @@ -315,7 +315,7 @@ public class SslConnection extends AbstractConnection getFillInterest().onFail(x); getWriteFlusher().onFail(x); } - + },x); } }; @@ -352,7 +352,7 @@ public class SslConnection extends AbstractConnection // all data could be wrapped. So either we need to write some encrypted data, // OR if we are handshaking we need to read some encrypted data OR // if neither then we should just try the flush again. - boolean flush = false; + boolean try_again = false; synchronized (DecryptedEndPoint.this) { if (DEBUG) @@ -373,10 +373,17 @@ public class SslConnection extends AbstractConnection } else { - flush = true; + // We can get here because the WriteFlusher might not see progress + // when it has just flushed the encrypted data, but not consumed anymore + // of the application buffers. This is mostly avoided by another iteration + // within DecryptedEndPoint flush(), but I cannot convince myself that + // this is never ever the case. + try_again = true; } } - if (flush) + + + if (try_again) { // If the output is closed, if (isOutputShutdown()) @@ -388,7 +395,9 @@ public class SslConnection extends AbstractConnection else { // try to flush what is pending - getWriteFlusher().completeWrite(); + // because this is a special case (see above) we could probably + // avoid the dispatch, but best to be sure + getExecutor().execute(_runCompletWrite); } } } @@ -505,8 +514,15 @@ public class SslConnection extends AbstractConnection // Let's unwrap even if we have no net data because in that // case we want to fall through to the handshake handling int pos = BufferUtil.flipToFill(app_in); - SSLEngineResult unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in); - BufferUtil.flipToFlush(app_in, pos); + SSLEngineResult unwrapResult; + try + { + unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in); + } + finally + { + BufferUtil.flipToFlush(app_in, pos); + } if (DEBUG) LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult); @@ -514,7 +530,9 @@ public class SslConnection extends AbstractConnection HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus(); Status unwrapResultStatus = unwrapResult.getStatus(); - _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW; + // Extra check on unwrapResultStatus == OK with zero length buffer is due + // to SSL client on android (see bug #454773) + _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW || unwrapResultStatus == Status.OK && unwrapResult.bytesConsumed()==0 && unwrapResult.bytesProduced()==0; if (_underFlown) { @@ -547,6 +565,12 @@ public class SslConnection extends AbstractConnection // or shutting down the output. return -1; } + case NEED_UNWRAP: + { + // We expected to read more, but we got closed. + // Return -1 to indicate to the application to drive the close. + return -1; + } default: { throw new IllegalStateException(); @@ -640,7 +664,7 @@ public class SslConnection extends AbstractConnection } catch (Exception e) { - getEndPoint().close(); + close(); throw e; } finally @@ -710,24 +734,26 @@ public class SslConnection extends AbstractConnection // We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer BufferUtil.compact(_encryptedOutput); int pos = BufferUtil.flipToFill(_encryptedOutput); - SSLEngineResult wrapResult = _sslEngine.wrap(appOuts, _encryptedOutput); + SSLEngineResult wrapResult; + try + { + wrapResult=_sslEngine.wrap(appOuts, _encryptedOutput); + } + finally + { + BufferUtil.flipToFlush(_encryptedOutput, pos); + } + if (DEBUG) LOG.debug("{} wrap {}", SslConnection.this, wrapResult); - BufferUtil.flipToFlush(_encryptedOutput, pos); if (wrapResult.bytesConsumed()>0) consumed+=wrapResult.bytesConsumed(); + Status wrapResultStatus = wrapResult.getStatus(); boolean allConsumed=true; - // clear empty buffers to prevent position creeping up the buffer for (ByteBuffer b : appOuts) - { - if (BufferUtil.isEmpty(b)) - BufferUtil.clear(b); - else + if (BufferUtil.hasContent(b)) allConsumed=false; - } - - Status wrapResultStatus = wrapResult.getStatus(); // and deal with the results returned from the sslEngineWrap switch (wrapResultStatus) @@ -774,19 +800,26 @@ public class SslConnection extends AbstractConnection { if (DEBUG) LOG.debug("{} renegotiation denied", SslConnection.this); - shutdownOutput(); + getEndPoint().shutdownOutput(); return allConsumed; } // if we have net bytes, let's try to flush them if (BufferUtil.hasContent(_encryptedOutput)) - getEndPoint().flush(_encryptedOutput); + if (!getEndPoint().flush(_encryptedOutput)) + getEndPoint().flush(_encryptedOutput); // one retry // But we also might have more to do for the handshaking state. switch (handshakeStatus) { case NOT_HANDSHAKING: - // Return with the number of bytes consumed (which may be 0) + // If we have not consumed all and had just finished handshaking, then we may + // have just flushed the last handshake in the encrypted buffers, so we should + // try again. + if (!allConsumed && wrapResult.getHandshakeStatus()==HandshakeStatus.FINISHED && BufferUtil.isEmpty(_encryptedOutput)) + continue; + + // Return true if we consumed all the bytes and encrypted are all flushed return allConsumed && BufferUtil.isEmpty(_encryptedOutput); case NEED_TASK: @@ -818,11 +851,6 @@ public class SslConnection extends AbstractConnection } } } - catch (Exception e) - { - getEndPoint().close(); - throw e; - } finally { if (DEBUG)