--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.java Tue Jan 30 17:39:58 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.java Tue Jan 30 20:43:32 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
package jdk.incubator.http.internal.websocket;
import jdk.incubator.http.WebSocket.MessagePart;
-import jdk.incubator.http.internal.common.Log;
import jdk.incubator.http.internal.websocket.Frame.Opcode;
import java.nio.ByteBuffer;
@@ -50,6 +49,7 @@
/* Non-final for testing purposes only */
class FrameConsumer implements Frame.Consumer {
+ private final static boolean DEBUG = true;
private final MessageStreamConsumer output;
private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder();
private boolean fin;
@@ -70,13 +70,17 @@
@Override
public void fin(boolean value) {
- Log.logTrace("Reading fin: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading fin: %s%n", value);
+ }
fin = value;
}
@Override
public void rsv1(boolean value) {
- Log.logTrace("Reading rsv1: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading rsv1: %s%n", value);
+ }
if (value) {
throw new FailWebSocketException("Unexpected rsv1 bit");
}
@@ -84,7 +88,9 @@
@Override
public void rsv2(boolean value) {
- Log.logTrace("Reading rsv2: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading rsv2: %s%n", value);
+ }
if (value) {
throw new FailWebSocketException("Unexpected rsv2 bit");
}
@@ -92,7 +98,9 @@
@Override
public void rsv3(boolean value) {
- Log.logTrace("Reading rsv3: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading rsv3: %s%n", value);
+ }
if (value) {
throw new FailWebSocketException("Unexpected rsv3 bit");
}
@@ -100,7 +108,9 @@
@Override
public void opcode(Opcode v) {
- Log.logTrace("Reading opcode: {0}", v);
+ if (DEBUG) {
+ System.out.printf("Reading opcode: %s%n", v);
+ }
if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
if (!fin) {
throw new FailWebSocketException("Fragmented control frame " + v);
@@ -122,13 +132,15 @@
}
opcode = v;
} else {
- throw new FailWebSocketException("Unknown opcode " + v);
+ throw new FailWebSocketException("Unexpected opcode " + v);
}
}
@Override
public void mask(boolean value) {
- Log.logTrace("Reading mask: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading mask: %s%n", value);
+ }
if (value) {
throw new FailWebSocketException("Masked frame received");
}
@@ -136,7 +148,9 @@
@Override
public void payloadLen(long value) {
- Log.logTrace("Reading payloadLen: {0}", value);
+ if (DEBUG) {
+ System.out.printf("Reading payloadLen: %s%n", value);
+ }
if (opcode.isControl()) {
if (value > 125) {
throw new FailWebSocketException(
@@ -164,7 +178,9 @@
@Override
public void payloadData(ByteBuffer data) {
- Log.logTrace("Reading payloadData: data={0}", data);
+ if (DEBUG) {
+ System.out.printf("Reading payloadData: %s%n", data);
+ }
unconsumedPayloadLen -= data.remaining();
boolean isLast = unconsumedPayloadLen == 0;
if (opcode.isControl()) {
@@ -207,6 +223,9 @@
@Override
public void endFrame() {
+ if (DEBUG) {
+ System.out.println("End frame");
+ }
if (opcode.isControl()) {
binaryData.flip();
}
--- a/test/jdk/java/net/httpclient/websocket/Exceptionally.java Tue Jan 30 17:39:58 2018 +0000
+++ b/test/jdk/java/net/httpclient/websocket/Exceptionally.java Tue Jan 30 20:43:32 2018 +0000
@@ -37,6 +37,7 @@
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
+import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -317,4 +318,65 @@
assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(0)));
}
}
+
+ @Test
+ public void testIllegalStateOnClose() throws Exception {
+ DummyWebSocketServer server = new DummyWebSocketServer() {
+ @Override
+ protected void serve(SocketChannel channel) throws IOException {
+ ByteBuffer closeMessage = ByteBuffer.wrap(new byte[]{(byte) 0x88, 0x00});
+ int wrote = channel.write(closeMessage);
+ System.out.println("Wrote bytes: " + wrote);
+ super.serve(channel);
+ }
+ };
+ try (server) {
+ server.open();
+ CompletableFuture<Void> onCloseCalled = new CompletableFuture<>();
+ CompletableFuture<Void> canClose = new CompletableFuture<>();
+
+ WebSocket ws = newHttpClient()
+ .newWebSocketBuilder()
+ .buildAsync(server.getURI(), new WebSocket.Listener() {
+ @Override
+ public CompletionStage<?> onClose(WebSocket webSocket,
+ int statusCode,
+ String reason) {
+ System.out.println("onClose(" + statusCode + ")");
+ onCloseCalled.complete(null);
+ return canClose;
+ }
+
+ @Override
+ public void onError(WebSocket webSocket, Throwable error) {
+ System.out.println("onError(" + error + ")");
+ error.printStackTrace();
+ }
+ })
+ .join();
+
+ onCloseCalled.join(); // Wait for onClose to be called
+ TimeUnit.SECONDS.sleep(5); // Give canClose some time to reach the WebSocket
+ canClose.complete(null); // Signal to the WebSocket it can close the output
+
+ assertCompletesExceptionally(ISE, ws.sendText("", true));
+ assertCompletesExceptionally(ISE, ws.sendText("", false));
+ assertCompletesExceptionally(ISE, ws.sendText("abc", true));
+ assertCompletesExceptionally(ISE, ws.sendText("abc", false));
+ assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(0), true));
+ assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(0), false));
+ assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(1), true));
+ assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(1), false));
+
+ assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(125)));
+ assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(124)));
+ assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(1)));
+ assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(0)));
+
+ assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(125)));
+ assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(124)));
+ assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(1)));
+ assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(0)));
+ }
+ }
}