From bf3c5c79224b70d43d1e92c9378e8b74548101fe Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Thu, 13 Dec 2012 12:15:47 -0600 Subject: [PATCH] add in some handshake state tracking into IOState to help track who initiated closes --- .../jetty/websocket/common/io/IOState.java | 38 ++++++++++++++ .../jetty/websocket/server/ab/Fuzzer.java | 51 ++++++++++++++++++- .../server/blockhead/BlockheadClient.java | 4 +- 3 files changed, 90 insertions(+), 3 deletions(-) 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 e9340e49440..420a2b606fd 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 @@ -36,11 +36,18 @@ public class IOState private final AtomicBoolean inputClosed; private final AtomicBoolean outputClosed; + private final AtomicBoolean cleanClose; + private final AtomicBoolean remoteCloseInitiated; + private final AtomicBoolean localCloseInitiated; + public IOState() { this.state = ConnectionState.CONNECTING; this.inputClosed = new AtomicBoolean(false); this.outputClosed = new AtomicBoolean(false); + this.remoteCloseInitiated = new AtomicBoolean(false); + this.localCloseInitiated = new AtomicBoolean(false); + this.cleanClose = new AtomicBoolean(false); } public void assertInputOpen() throws IOException @@ -111,11 +118,21 @@ public class IOState { in = true; this.inputClosed.set(true); + + if (!localCloseInitiated.get()) + { + remoteCloseInitiated.set(true); + } } else { out = true; this.outputClosed.set(true); + + if ( !remoteCloseInitiated.get() ) + { + localCloseInitiated.set(true); + } } LOG.debug("onCloseHandshake({},{}), input={}, output={}",incoming,close,in,out); @@ -123,6 +140,7 @@ public class IOState if (in && out) { LOG.debug("Close Handshake satisfied, disconnecting"); + cleanClose.set(true); return true; } @@ -144,4 +162,24 @@ public class IOState { this.state = state; } + + public boolean isCloseInitiated() + { + return remoteCloseInitiated.get() || localCloseInitiated.get(); + } + + public boolean wasRemoteCloseInitiated() + { + return remoteCloseInitiated.get(); + } + + public boolean wasLocalCloseInitiated() + { + return localCloseInitiated.get(); + } + + public boolean wasCleanClose() + { + return cleanClose.get(); + } } 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 3f3d4a3c937..88682c2c083 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 @@ -38,6 +38,7 @@ import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.io.IOState; import org.eclipse.jetty.websocket.server.ByteBufferAssert; import org.eclipse.jetty.websocket.server.blockhead.BlockheadClient; import org.eclipse.jetty.websocket.server.helper.IncomingFramesCapture; @@ -55,6 +56,13 @@ public class Fuzzer SLOW } + public static enum CloseState + { + OPEN, + REMOTE_INITIATED, + LOCAL_INITIATED + } + private static final int KBYTE = 1024; private static final int MBYTE = KBYTE * KBYTE; @@ -178,7 +186,30 @@ public class Fuzzer public void expectServerClose(boolean wasClean) throws IOException, InterruptedException { - // DOES NOT WORK -- Assert.assertThat("Should have disconnected",client.awaitDisconnect(2,TimeUnit.SECONDS),is(true)); + // we expect that the close handshake to have occurred and the server should have closed the connection + try + { + int val = client.read(); + + Assert.fail("Server has not closed socket"); + } + catch (SocketException e) + { + + } + + IOState ios = client.getIOState(); + + if (wasClean) + { + Assert.assertTrue(ios.wasRemoteCloseInitiated()); + Assert.assertTrue(ios.wasCleanClose()); + } + else + { + Assert.assertTrue(ios.wasRemoteCloseInitiated()); + } + } public SendMode getSendMode() @@ -327,4 +358,22 @@ public class Fuzzer { this.slowSendSegmentSize = segmentSize; } + + public CloseState getCloseState() + { + IOState ios = client.getIOState(); + + if ( ios.wasLocalCloseInitiated() ) + { + return CloseState.LOCAL_INITIATED; + } + else if ( ios.wasRemoteCloseInitiated() ) + { + return CloseState.REMOTE_INITIATED; + } + else + { + return CloseState.OPEN; + } + } } 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 22f2e726b3a..8c8d1765593 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 @@ -116,7 +116,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames private ExtensionStack extensionStack; private IOState ioState; private CountDownLatch disconnectedLatch = new CountDownLatch(1); - + public BlockheadClient(URI destWebsocketURI) throws URISyntaxException { this(WebSocketPolicy.newClientPolicy(),destWebsocketURI); @@ -173,7 +173,7 @@ public class BlockheadClient implements IncomingFrames, OutgoingFrames public void close(int statusCode, String message) { try - { + { CloseInfo close = new CloseInfo(statusCode,message); if (ioState.onCloseHandshake(false,close))