diff options
author | Jesse McConnell | 2013-06-21 20:18:46 +0000 |
---|---|---|
committer | Jesse McConnell | 2013-06-21 20:18:46 +0000 |
commit | 018a51a04e81c29b00783eaba24e077456a1dd45 (patch) | |
tree | 0d850f26008ecf2b74bc31a3052414ad1510066d /jetty-websocket | |
parent | 57bfda2a0829fca0773fbcadcacd2795a094cc09 (diff) | |
parent | ebe98022abf5d67cd08d454af69e544f850c0609 (diff) | |
download | org.eclipse.jetty.project-018a51a04e81c29b00783eaba24e077456a1dd45.tar.gz org.eclipse.jetty.project-018a51a04e81c29b00783eaba24e077456a1dd45.tar.xz org.eclipse.jetty.project-018a51a04e81c29b00783eaba24e077456a1dd45.zip |
Merge branch 'master' into release-9
Diffstat (limited to 'jetty-websocket')
11 files changed, 190 insertions, 132 deletions
diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java index cf37519d0a..032c45c121 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java @@ -141,6 +141,21 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp return String.format("%s@%x",FlushInvoker.class.getSimpleName(),hashCode()); } } + + public class OnDisconnectCallback implements WriteCallback + { + @Override + public void writeFailed(Throwable x) + { + disconnect(); + } + + @Override + public void writeSuccess() + { + disconnect(); + } + } public static class Stats { @@ -233,6 +248,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp @Override public void disconnect() { + LOG.debug("{} disconnect()", policy.getBehavior()); synchronized (writeBytes) { if (!writeBytes.isClosed()) @@ -426,7 +442,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp @Override public void onConnectionStateChange(ConnectionState state) { - LOG.debug("Connection State Change: {}",state); + LOG.debug("{} Connection State Change: {}",policy.getBehavior(),state); switch (state) { case OPEN: @@ -439,7 +455,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp case CLOSING: CloseInfo close = ioState.getCloseInfo(); // append close frame - outgoingFrame(close.asFrame(),null); + outgoingFrame(close.asFrame(),new OnDisconnectCallback()); default: break; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java index 3836ae6633..e5bfd086d4 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java @@ -182,11 +182,13 @@ public class IOState */ public void onCloseLocal(CloseInfo close) { + LOG.debug("onCloseLocal({})",close); ConnectionState event = null; ConnectionState initialState = this.state; if (initialState == ConnectionState.CLOSED) { // already closed + LOG.debug("already closed"); return; } @@ -224,15 +226,19 @@ public class IOState event = this.state; } } + + LOG.debug("event = {}",event); // Only notify on state change events if (event != null) { + LOG.debug("notifying state listeners: {}",event); notifyStateListeners(event); - // if SHUTDOWN, we don't expect an answer. - if (close.getStatusCode() == StatusCode.SHUTDOWN) + // if harsh, we don't expect an answer. + if (close.isHarsh()) { + LOG.debug("Harsh close, disconnecting"); synchronized (this.state) { this.state = ConnectionState.CLOSED; @@ -253,6 +259,7 @@ public class IOState */ public void onCloseRemote(CloseInfo close) { + LOG.debug("onCloseRemote({})",close); ConnectionState event = null; synchronized (this.state) { diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java index 752972d785..f899941a89 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerConnection.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.common.ConnectionState; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; public class WebSocketServerConnection extends AbstractWebSocketConnection @@ -74,7 +75,7 @@ public class WebSocketServerConnection extends AbstractWebSocketConnection } super.onOpen(); } - + @Override public void setNextIncomingFrames(IncomingFrames incoming) { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java index 21ffcaeda6..97e34c6625 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java @@ -23,8 +23,12 @@ import static org.hamcrest.Matchers.*; import java.io.IOException; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.common.CloseInfo; +import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient; +import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; @@ -69,7 +73,7 @@ public class IdleTimeoutTest { BlockheadClient client = new BlockheadClient(server.getServerUri()); client.setProtocols("onConnect"); - client.setTimeout(TimeUnit.MILLISECONDS,1500); + client.setTimeout(TimeUnit.MILLISECONDS,2500); try { client.connect(); @@ -83,13 +87,15 @@ public class IdleTimeoutTest // Write to server (the server should be timed out and disconnect now) client.write(WebSocketFrame.text("Hello")); - // now attempt to read 2 echoed frames from server (shouldn't work) - client.readFrames(2,TimeUnit.MILLISECONDS,1500); - Assert.fail("Should have resulted in IOException"); - } - catch (IOException e) - { - Assert.assertThat("IOException",e.getMessage(),anyOf(containsString("closed"),containsString("disconnected"))); + // now read 1 frame from server (should be close frame) + IncomingFramesCapture capture = client.readFrames(1,TimeUnit.MILLISECONDS,1500); + WebSocketFrame frame = capture.getFrames().poll(); + Assert.assertThat("Was close frame", frame.getOpCode(), is(OpCode.CLOSE)); + CloseInfo close = new CloseInfo(frame); + Assert.assertThat("Close.code", close.getStatusCode(), is(StatusCode.SHUTDOWN)); + Assert.assertThat("Close.reason", close.getReason(), containsString("Idle Timeout")); + + client.expectServerDisconnect(); } finally { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java index f0676b1c8c..89ea415535 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java @@ -65,7 +65,9 @@ public class WebSocketOverSSLTest client.start(); CaptureSocket clientSocket = new CaptureSocket(); - Future<Session> fut = client.connect(clientSocket,server.getServerUri()); + URI requestUri = server.getServerUri(); + System.err.printf("Request URI: %s%n",requestUri.toASCIIString()); + Future<Session> fut = client.connect(clientSocket,requestUri); // wait for connect Session session = fut.get(3,TimeUnit.SECONDS); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java index 5c9d07c6f7..82b2ce94e3 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/Fuzzer.java @@ -62,13 +62,18 @@ public class Fuzzer PER_FRAME, SLOW } + + public static enum DisconnectMode + { + /** Disconnect occurred after a proper close handshake */ + CLEAN, + /** Disconnect occurred in a harsh manner, without a close handshake */ + UNCLEAN + } private static final int KBYTE = 1024; private static final int MBYTE = KBYTE * KBYTE; - public static final boolean CLEAN_CLOSE = true; - public static final boolean NOT_CLEAN_CLOSE = false; - private static final Logger LOG = Log.getLogger(Fuzzer.class); // Client side framing mask @@ -88,6 +93,7 @@ public class Fuzzer int bigMessageSize = 20 * MBYTE; policy.setMaxMessageSize(bigMessageSize); + policy.setIdleTimeout(5000); this.client = new BlockheadClient(policy,testcase.getServer().getServerUri()); this.generator = testcase.getLaxGenerator(); @@ -183,35 +189,21 @@ public class Fuzzer // TODO Should test for no more frames. success if connection closed. } - public void expectServerClose(boolean wasClean) throws IOException, InterruptedException + public void expectServerDisconnect(DisconnectMode mode) { - // we expect that the close handshake to have occurred and the server should have closed the connection - try - { - ByteBuffer buf = ByteBuffer.wrap(new byte[] - { 0x00 }); - BufferUtil.flipToFill(buf); - int len = client.read(buf); - - Assert.assertThat("Server has not closed socket",len,lessThanOrEqualTo(0)); - } - catch (IOException e) - { - // valid path - } - + client.expectServerDisconnect(); IOState ios = client.getIOState(); - if (wasClean) - { - Assert.assertTrue(ios.wasRemoteCloseInitiated()); - Assert.assertTrue(ios.wasCleanClose()); - } - else + switch (mode) { - Assert.assertTrue(ios.wasRemoteCloseInitiated()); + case CLEAN: + Assert.assertTrue(ios.wasRemoteCloseInitiated()); + Assert.assertTrue(ios.wasCleanClose()); + break; + case UNCLEAN: + Assert.assertTrue(ios.wasRemoteCloseInitiated()); + break; } - } public CloseState getCloseState() @@ -342,20 +334,6 @@ public class Fuzzer } } - public void sendExpectingIOException(ByteBuffer part3) - { - try - { - send(part3); - Assert.fail("Expected a IOException on this send"); - } - catch (IOException ignore) - { - // Send, but expect the send to fail with a IOException. - // Usually, this is a SocketException("Socket Closed") condition. - } - } - private void setClientMask(WebSocketFrame f) { if (LOG.isDebugEnabled()) diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java index 5cecc19726..a3e183cfa1 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase1.java @@ -51,7 +51,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); - fuzzer.expectServerClose(Fuzzer.CLEAN_CLOSE); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -83,6 +83,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -114,6 +115,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -145,6 +147,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -176,6 +179,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -207,6 +211,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -238,6 +243,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -275,6 +281,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSlowSendSegmentSize(segmentSize); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -303,6 +310,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -334,6 +342,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -365,6 +374,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -396,6 +406,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -427,6 +438,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -458,6 +470,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -489,6 +502,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSendMode(SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { @@ -526,6 +540,7 @@ public class TestABCase1 extends AbstractABCase fuzzer.setSlowSendSegmentSize(segmentSize); fuzzer.send(send); fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); } finally { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java index 873764c170..3a9f5e1576 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java @@ -24,6 +24,7 @@ import java.util.List; import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; @@ -236,32 +237,32 @@ public class TestABCase2 extends AbstractABCase @Test public void testCase2_5() throws Exception { - // Disable Long Stacks from Parser (we know this test will throw an exception) - enableStacks(Parser.class,false); - - byte payload[] = new byte[126]; // intentionally too big - Arrays.fill(payload,(byte)'5'); - - List<WebSocketFrame> send = new ArrayList<>(); - // trick websocket frame into making extra large payload for ping - send.add(WebSocketFrame.binary(payload).setOpCode(OpCode.PING)); - send.add(new CloseInfo(StatusCode.NORMAL,"Test 2.5").asFrame()); - - List<WebSocketFrame> expect = new ArrayList<>(); - expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); - - Fuzzer fuzzer = new Fuzzer(this); - try + try(StacklessLogging scope = new StacklessLogging(Parser.class)) { - fuzzer.connect(); - fuzzer.setSendMode(Fuzzer.SendMode.BULK); - fuzzer.send(send); - fuzzer.expect(expect); - } - finally - { - enableStacks(Parser.class,true); - fuzzer.close(); + byte payload[] = new byte[126]; // intentionally too big + Arrays.fill(payload,(byte)'5'); + + List<WebSocketFrame> send = new ArrayList<>(); + // trick websocket frame into making extra large payload for ping + send.add(WebSocketFrame.binary(payload).setOpCode(OpCode.PING)); + send.add(new CloseInfo(StatusCode.NORMAL,"Test 2.5").asFrame()); + + List<WebSocketFrame> expect = new ArrayList<>(); + expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame()); + + Fuzzer fuzzer = new Fuzzer(this); + try + { + fuzzer.connect(); + fuzzer.setSendMode(Fuzzer.SendMode.BULK); + fuzzer.send(send); + fuzzer.expect(expect); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.CLEAN); + } + finally + { + fuzzer.close(); + } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java index fbf87f8481..b7aa7b37cf 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; +import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.OpCode; @@ -358,54 +359,55 @@ public class TestABCase6 extends AbstractABCase public void testCase6_4_3() throws Exception { // Disable Long Stacks from Parser (we know this test will throw an exception) - enableStacks(Parser.class,false); - - ByteBuffer payload = ByteBuffer.allocate(64); - BufferUtil.clearToFill(payload); - payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good - payload.put(TypeUtil.fromHexString("f4908080")); // INVALID - payload.put(TypeUtil.fromHexString("656469746564")); // good - BufferUtil.flipToFlush(payload,0); - - List<WebSocketFrame> send = new ArrayList<>(); - send.add(new WebSocketFrame(OpCode.TEXT).setPayload(payload)); - send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); - - List<WebSocketFrame> expect = new ArrayList<>(); - expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame()); - - Fuzzer fuzzer = new Fuzzer(this); - try + try(StacklessLogging scope = new StacklessLogging(Parser.class)) { - fuzzer.connect(); - - ByteBuffer net = fuzzer.asNetworkBuffer(send); - - int splits[] = - { 17, 21, net.limit() }; - - ByteBuffer part1 = net.slice(); // Header + good UTF - part1.limit(splits[0]); - ByteBuffer part2 = net.slice(); // invalid UTF - part2.position(splits[0]); - part2.limit(splits[1]); - ByteBuffer part3 = net.slice(); // good UTF - part3.position(splits[1]); - part3.limit(splits[2]); - - fuzzer.send(part1); // the header + good utf - TimeUnit.SECONDS.sleep(1); - fuzzer.send(part2); // the bad UTF - - fuzzer.expect(expect); - - TimeUnit.SECONDS.sleep(1); - fuzzer.sendExpectingIOException(part3); // the rest (shouldn't work) - } - finally - { - enableStacks(Parser.class,true); - fuzzer.close(); + ByteBuffer payload = ByteBuffer.allocate(64); + BufferUtil.clearToFill(payload); + payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good + payload.put(TypeUtil.fromHexString("f4908080")); // INVALID + payload.put(TypeUtil.fromHexString("656469746564")); // good + BufferUtil.flipToFlush(payload,0); + + List<WebSocketFrame> send = new ArrayList<>(); + send.add(new WebSocketFrame(OpCode.TEXT).setPayload(payload)); + send.add(new CloseInfo(StatusCode.NORMAL).asFrame()); + + List<WebSocketFrame> expect = new ArrayList<>(); + expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame()); + + Fuzzer fuzzer = new Fuzzer(this); + try + { + fuzzer.connect(); + + ByteBuffer net = fuzzer.asNetworkBuffer(send); + + int splits[] = + { 17, 21, net.limit() }; + + ByteBuffer part1 = net.slice(); // Header + good UTF + part1.limit(splits[0]); + ByteBuffer part2 = net.slice(); // invalid UTF + part2.position(splits[0]); + part2.limit(splits[1]); + ByteBuffer part3 = net.slice(); // good UTF + part3.position(splits[1]); + part3.limit(splits[2]); + + fuzzer.send(part1); // the header + good utf + TimeUnit.SECONDS.sleep(1); + fuzzer.send(part2); // the bad UTF + + fuzzer.expect(expect); + + TimeUnit.SECONDS.sleep(1); + fuzzer.send(part3); // the rest (shouldn't work) + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.UNCLEAN); + } + finally + { + fuzzer.close(); + } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java index b93b6ba2fa..6767586a4b 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6_BadUTF.java @@ -168,7 +168,7 @@ public class TestABCase6_BadUTF extends AbstractABCase fuzzer.setSendMode(Fuzzer.SendMode.BULK); fuzzer.send(send); fuzzer.expect(expect); - fuzzer.expectServerClose(Fuzzer.NOT_CLEAN_CLOSE); + fuzzer.expectServerDisconnect(Fuzzer.DisconnectMode.UNCLEAN); } finally { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java index 4b1f7358a0..8573c93133 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/blockhead/BlockheadClient.java @@ -29,6 +29,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; +import java.net.SocketTimeoutException; import java.net.URI; import java.net.URISyntaxException; import java.nio.ByteBuffer; @@ -125,10 +126,8 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames, Connecti { Assert.assertThat("Websocket URI scheme",destWebsocketURI.getScheme(),anyOf(is("ws"),is("wss"))); this.destWebsocketURI = destWebsocketURI; - String scheme = "http"; if (destWebsocketURI.getScheme().equals("wss")) { - scheme = "https"; throw new RuntimeException("Sorry, BlockheadClient does not support SSL"); } this.destHttpURI = WSURI.toHttp(destWebsocketURI); @@ -415,7 +414,8 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames, Connecti switch (state) { case CLOSED: - this.disconnect(); + // Per Spec, client should not initiate disconnect on its own + // this.disconnect(); break; case CLOSING: if (ioState.wasRemoteCloseInitiated()) @@ -465,6 +465,36 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames, Connecti } } + public void expectServerDisconnect() + { + if (eof) + { + return; + } + + try + { + int len = in.read(); + if (len == (-1)) + { + // we are disconnected + eof = true; + return; + } + + Assert.assertThat("Expecting no data and proper socket disconnect (issued from server)",len,is(-1)); + } + catch (SocketTimeoutException e) + { + LOG.warn(e); + Assert.fail("Expected a server initiated disconnect, instead the read timed out"); + } + catch (IOException e) + { + // acceptable path + } + } + public int read(ByteBuffer buf) throws IOException { if (eof) |