diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java index f6adcfbfc9c..1fc776ae339 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/WriteFlusher.java @@ -268,7 +268,7 @@ abstract public class WriteFlusher if (_callback!=null) _callback.succeeded(); } - + boolean isCallbackNonBlocking() { return _callback!=null && _callback.isNonBlocking(); @@ -280,7 +280,7 @@ abstract public class WriteFlusher State s = _state.get(); return (s instanceof PendingState) && ((PendingState)s).isCallbackNonBlocking(); } - + /** * Abstract call to be implemented by specific WriteFlushers. It should schedule a call to {@link #completeWrite()} * or {@link #onFail(Throwable)} when appropriate. @@ -355,7 +355,7 @@ abstract public class WriteFlusher * {@link #onFail(Throwable)} or {@link #onClose()} */ public void completeWrite() - { + { if (DEBUG) LOG.debug("completeWrite: {}", this); @@ -404,8 +404,9 @@ abstract public class WriteFlusher } } - /* ------------------------------------------------------------ */ - /** Flush the buffers iteratively until no progress is made + /** + * Flushes the buffers iteratively until no progress is made. + * * @param buffers The buffers to flush * @return The unflushed buffers, or null if all flushed * @throws IOException if unable to flush @@ -418,15 +419,15 @@ abstract public class WriteFlusher int before=buffers.length==0?0:buffers[0].remaining(); boolean flushed=_endPoint.flush(buffers); int r=buffers.length==0?0:buffers[0].remaining(); - + if (LOG.isDebugEnabled()) LOG.debug("Flushed={} {}/{}+{} {}",flushed,before-r,before,buffers.length-1,this); - + if (flushed) return null; - + progress=before!=r; - + int not_empty=0; while(r==0) { @@ -442,17 +443,17 @@ abstract public class WriteFlusher if (not_empty>0) buffers=Arrays.copyOfRange(buffers,not_empty,buffers.length); - } + } if (LOG.isDebugEnabled()) LOG.debug("!fully flushed {}",this); - + // If buffers is null, then flush has returned false but has consumed all the data! // This is probably SSL being unable to flush the encrypted buffer, so return EMPTY_BUFFERS // and that will keep this WriteFlusher pending. return buffers==null?EMPTY_BUFFERS:buffers; } - + /* ------------------------------------------------------------ */ /** Notify the flusher of a failure * @param cause The cause of the failure @@ -522,7 +523,7 @@ abstract public class WriteFlusher { return String.format("WriteFlusher@%x{%s}", hashCode(), _state.get()); } - + public String toStateString() { switch(_state.get().getType()) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java index 2c3197bab2b..1ef6d271f79 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java @@ -576,7 +576,7 @@ public class SslConnection extends AbstractConnection { _handshaken = true; if (LOG.isDebugEnabled()) - LOG.debug("{} {} handshook {}/{}", SslConnection.this, + LOG.debug("{} {} handshake succeeded {}/{}", SslConnection.this, _sslEngine.getUseClientMode() ? "client" : "resumed server", _sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite()); } @@ -758,6 +758,7 @@ public class SslConnection extends AbstractConnection switch (wrapResultStatus) { case CLOSED: + { // The SSL engine has close, but there may be close handshake that needs to be written if (BufferUtil.hasContent(_encryptedOutput)) { @@ -777,11 +778,13 @@ public class SslConnection extends AbstractConnection getEndPoint().shutdownOutput(); } return allConsumed; - + } case BUFFER_UNDERFLOW: + { throw new IllegalStateException(); - + } default: + { if (LOG.isDebugEnabled()) LOG.debug("{} wrap {} {}", SslConnection.this, wrapResultStatus, BufferUtil.toHexSummary(_encryptedOutput)); @@ -789,7 +792,7 @@ public class SslConnection extends AbstractConnection { _handshaken = true; if (LOG.isDebugEnabled()) - LOG.debug("{} server handshook complete {}/{}", SslConnection.this, _sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite()); + LOG.debug("{} server handshake succeeded {}/{}", SslConnection.this, _sslEngine.getSession().getProtocol(),_sslEngine.getSession().getCipherSuite()); } HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus(); @@ -847,6 +850,7 @@ public class SslConnection extends AbstractConnection case FINISHED: throw new IllegalStateException(); } + } } } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java index 9f0e43358fd..7d48e24b405 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslConnectionFactoryTest.java @@ -59,11 +59,11 @@ import org.junit.Before; import org.junit.Test; public class SslConnectionFactoryTest -{ +{ Server _server; ServerConnector _connector; int _port; - + @Before public void before() throws Exception { @@ -83,7 +83,7 @@ public class SslConnectionFactoryTest HttpConfiguration https_config = new HttpConfiguration(http_config); https_config.addCustomizer(new SecureRequestCustomizer()); - + SslContextFactory sslContextFactory = new SslContextFactory(); sslContextFactory.setKeyStorePath(keystoreFile.getAbsolutePath()); sslContextFactory.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4"); @@ -96,7 +96,7 @@ public class SslConnectionFactoryTest https.setIdleTimeout(30000); _server.addConnector(https); - + _server.setHandler(new AbstractHandler() { @Override @@ -107,30 +107,30 @@ public class SslConnectionFactoryTest response.flushBuffer(); } }); - + _server.start(); - _port=https.getLocalPort(); + _port=https.getLocalPort(); } - + @After public void after() throws Exception { _server.stop(); _server=null; } - + @Test public void testConnect() throws Exception { - String response= getResponse("127.0.0.1",null); + String response= getResponse("127.0.0.1",null); Assert.assertThat(response,Matchers.containsString("host=127.0.0.1")); } - + @Test public void testSNIConnect() throws Exception { String response; - + response= getResponse("localhost","localhost","jetty.eclipse.org"); Assert.assertThat(response,Matchers.containsString("host=localhost")); } @@ -151,22 +151,21 @@ public class SslConnectionFactoryTest { out.write("Rubbish".getBytes()); out.flush(); - + Assert.assertThat(socket.getInputStream().read(),Matchers.equalTo(-1)); } - } - + private String getResponse(String sniHost,String reqHost, String cn) throws Exception { SslContextFactory clientContextFactory = new SslContextFactory(true); clientContextFactory.start(); SSLSocketFactory factory = clientContextFactory.getSslContext().getSocketFactory(); - + SSLSocket sslSocket = (SSLSocket)factory.createSocket("127.0.0.1", _port); if (cn!=null) - { + { SNIHostName serverName = new SNIHostName(sniHost); List serverNames = new ArrayList<>(); serverNames.add(serverName); @@ -177,35 +176,35 @@ public class SslConnectionFactoryTest } sslSocket.startHandshake(); - + if (cn!=null) - { + { X509Certificate cert = ((X509Certificate)sslSocket.getSession().getPeerCertificates()[0]); - + Assert.assertThat(cert.getSubjectX500Principal().getName("CANONICAL"), Matchers.startsWith("cn="+cn)); } sslSocket.getOutputStream().write(("GET /ctx/path HTTP/1.0\r\nHost: "+reqHost+":"+_port+"\r\n\r\n").getBytes(StandardCharsets.ISO_8859_1)); String response = IO.toString(sslSocket.getInputStream()); - + sslSocket.close(); clientContextFactory.stop(); return response; } - + @Test public void testSocketCustomization() throws Exception { final Queue history = new ConcurrentArrayQueue<>(); - + _connector.addBean(new SocketCustomizationListener() { @Override protected void customize(Socket socket, Class connection, boolean ssl) { history.add("customize connector "+connection+","+ssl); - } + } }); _connector.getBean(SslConnectionFactory.class).addBean(new SocketCustomizationListener() @@ -214,26 +213,26 @@ public class SslConnectionFactoryTest protected void customize(Socket socket, Class connection, boolean ssl) { history.add("customize ssl "+connection+","+ssl); - } + } }); - + _connector.getBean(HttpConnectionFactory.class).addBean(new SocketCustomizationListener() { @Override protected void customize(Socket socket, Class connection, boolean ssl) { history.add("customize http "+connection+","+ssl); - } + } }); - String response= getResponse("127.0.0.1",null); + String response= getResponse("127.0.0.1",null); Assert.assertThat(response,Matchers.containsString("host=127.0.0.1")); - + Assert.assertEquals("customize connector class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll()); Assert.assertEquals("customize ssl class org.eclipse.jetty.io.ssl.SslConnection,false",history.poll()); Assert.assertEquals("customize connector class org.eclipse.jetty.server.HttpConnection,true",history.poll()); Assert.assertEquals("customize http class org.eclipse.jetty.server.HttpConnection,true",history.poll()); Assert.assertEquals(0,history.size()); } - + }