/** * Splits the provided buffer into multiple frames (which do not exceed the maximum web socket frame size) * and writes them in order to the socket. */ private void writePartialMessage(FrameType frameType, Buffer data, int offset) { int end = offset + maxWebSocketFrameSize; boolean isFinal; if (end >= data.length()) { end = data.length(); isFinal = true; } else { isFinal = false; } Buffer slice = data.slice(offset, end); WebSocketFrame frame; if (offset == 0 || !supportsContinuation) { frame = new WebSocketFrameImpl(frameType, slice.getByteBuf(), isFinal); } else { frame = WebSocketFrame.continuationFrame(slice, isFinal); } writeFrame(frame); int newOffset = offset + maxWebSocketFrameSize; if (!isFinal) { writePartialMessage(frameType, data, newOffset); } }
@Test public void testWebsocketFrameFactoryArguments() throws Exception { assertNullPointerException(() -> WebSocketFrame.binaryFrame(null, true)); assertNullPointerException(() -> WebSocketFrame.textFrame(null, true)); assertNullPointerException(() -> WebSocketFrame.continuationFrame(null, true)); }
frame = WebSocketFrame.binaryFrame(buff, false); } else { frame = WebSocketFrame.continuationFrame(buff, j == frames - 1); frame = WebSocketFrame.textFrame(str, false); } else { frame = WebSocketFrame.continuationFrame(buff, j == frames - 1);
/** * Splits the provided buffer into multiple frames (which do not exceed the maximum web socket frame size) * and writes them in order to the socket. */ private void writePartialMessage(FrameType frameType, Buffer data, int offset) { int end = offset + maxWebSocketFrameSize; boolean isFinal; if (end >= data.length()) { end = data.length(); isFinal = true; } else { isFinal = false; } Buffer slice = data.slice(offset, end); WebSocketFrame frame; if (offset == 0 || !supportsContinuation) { frame = new WebSocketFrameImpl(frameType, slice.getByteBuf(), isFinal); } else { frame = WebSocketFrame.continuationFrame(slice, isFinal); } writeFrame(frame); int newOffset = offset + maxWebSocketFrameSize; if (!isFinal) { writePartialMessage(frameType, data, newOffset); } }
/** * Writing multiple continuation frames from the client side should result in a single message on the server side * after the frames are re-combined */ @Test public void testCombineBinaryContinuationFramesRawWebSocket() throws InterruptedException { String serverPath = "/combine"; AtomicReference<Buffer> serverReceivedMessage = new AtomicReference<>(); setupSockJsServer(serverPath, (sock, requestBuffer) -> { serverReceivedMessage.set(requestBuffer); sock.write(Buffer.buffer("reply")); sock.close(); }); Buffer largeMessage = Buffer.buffer(TestUtils.randomAlphaString(30)); WebSocketFrame frame1 = WebSocketFrame.binaryFrame(largeMessage.slice(0, 10), false); WebSocketFrame frame2 = WebSocketFrame.continuationFrame(largeMessage.slice(10, 20), false); WebSocketFrame frame3 = WebSocketFrame.continuationFrame(largeMessage.slice(20, largeMessage.length()), true); WebSocket ws = setupRawWebsocketClient(serverPath); ws.writeFrame(frame1); ws.writeFrame(frame2); ws.writeFrame(frame3); await(5, TimeUnit.SECONDS); assertEquals("Server did not combine continuation frames correctly", largeMessage, serverReceivedMessage.get()); }
@Test public void testWebsocketFrameFactoryArguments() throws Exception { assertNullPointerException(() -> WebSocketFrame.binaryFrame(null, true)); assertNullPointerException(() -> WebSocketFrame.textFrame(null, true)); assertNullPointerException(() -> WebSocketFrame.continuationFrame(null, true)); }
@Test public void testCombineTextFrameSockJs() throws InterruptedException { String serverPath = "/text-combine-sockjs"; setupSockJsServer(serverPath, this::echoRequest); List<Buffer> receivedMessages = new ArrayList<>(); WebSocket openedWebSocket = setupSockJsClient(serverPath, receivedMessages); Buffer largeMessage = Buffer.buffer("[\"" + TestUtils.randomAlphaString(30) + "\"]"); WebSocketFrame frame1 = new WebSocketFrameImpl(FrameType.TEXT, largeMessage.slice(0, 10).getByteBuf(), false); WebSocketFrame frame2 = WebSocketFrame.continuationFrame(largeMessage.slice(10, 20), false); WebSocketFrame frame3 = WebSocketFrame.continuationFrame(largeMessage.slice(20, largeMessage.length()), true); log.debug("Client sending " + frame1.textData()); openedWebSocket.writeFrame(frame1); log.debug("Client sending " + frame2.textData()); openedWebSocket.writeFrame(frame2); log.debug("Client sending " + frame3.textData()); openedWebSocket.writeFrame(frame3); await(5, TimeUnit.SECONDS); assertEquals("Client should have received 2 messages: the reply and the close.", 2, receivedMessages.size()); Buffer expectedReply = Buffer.buffer("a" + largeMessage.toString()); assertEquals("Client reply should have matched request", expectedReply, receivedMessages.get(0)); assertEquals("Final message should have been a close", SOCKJS_CLOSE_REPLY, receivedMessages.get(1)); }
frame = WebSocketFrame.binaryFrame(buff, false); } else { frame = WebSocketFrame.continuationFrame(buff, j == frames - 1); frame = WebSocketFrame.textFrame(str, false); } else { frame = WebSocketFrame.continuationFrame(buff, j == frames - 1);
@Test public void testCombineMultipleFramesIntoASingleMessage() throws Exception { socketHandler = () -> { return socket -> socket.handler(buf -> { assertEquals("Hello World", buf.toString()); testComplete(); }); }; startServers(); client.websocket("/test/400/8ne8e94a/websocket", ws -> { ws.writeFrame(io.vertx.core.http.WebSocketFrame.textFrame("[\"Hello", false)); ws.writeFrame(io.vertx.core.http.WebSocketFrame.continuationFrame(Buffer.buffer(" World\"]"), true)); ws.close(); }); await(); } }
@Test public void testSendWebsocketContinuationFrames() { // Use raw websocket transport client.websocket("/echo/websocket", ws -> { int size = 65535; Buffer buffer1 = TestUtils.randomBuffer(size); Buffer buffer2 = TestUtils.randomBuffer(size); ws.writeFrame(io.vertx.core.http.WebSocketFrame.binaryFrame(buffer1, false)); ws.writeFrame(io.vertx.core.http.WebSocketFrame.continuationFrame(buffer2, true)); Buffer received = Buffer.buffer(); ws.handler(buff -> { received.appendBuffer(buff); if (received.length() == size * 2) { testComplete(); } }); }); await(); }
/** * Create a continuation frame * @param data the data for the frame * @param isFinal true if it's the final frame in the WebSocket message * @return the frame */ public static io.vertx.rxjava.core.http.WebSocketFrame continuationFrame(io.vertx.rxjava.core.buffer.Buffer data, boolean isFinal) { io.vertx.rxjava.core.http.WebSocketFrame ret = io.vertx.rxjava.core.http.WebSocketFrame.newInstance(io.vertx.core.http.WebSocketFrame.continuationFrame(data.getDelegate(), isFinal)); return ret; }
/** * Create a continuation frame * @param data the data for the frame * @param isFinal true if it's the final frame in the WebSocket message * @return the frame */ public static io.vertx.rxjava.core.http.WebSocketFrame continuationFrame(io.vertx.rxjava.core.buffer.Buffer data, boolean isFinal) { io.vertx.rxjava.core.http.WebSocketFrame ret = io.vertx.rxjava.core.http.WebSocketFrame.newInstance(io.vertx.core.http.WebSocketFrame.continuationFrame(data.getDelegate(), isFinal)); return ret; }
/** * Writing multiple continuation frames from the client side should result in a single message on the server side * after the frames are re-combined */ @Test public void testCombineBinaryContinuationFramesRawWebSocket() throws InterruptedException { String serverPath = "/combine"; AtomicReference<Buffer> serverReceivedMessage = new AtomicReference<>(); setupSockJsServer(serverPath, (sock, requestBuffer) -> { serverReceivedMessage.set(requestBuffer); sock.write(Buffer.buffer("reply")); sock.close(); }); Buffer largeMessage = Buffer.buffer(TestUtils.randomAlphaString(30)); WebSocketFrame frame1 = WebSocketFrame.binaryFrame(largeMessage.slice(0, 10), false); WebSocketFrame frame2 = WebSocketFrame.continuationFrame(largeMessage.slice(10, 20), false); WebSocketFrame frame3 = WebSocketFrame.continuationFrame(largeMessage.slice(20, largeMessage.length()), true); WebSocket ws = setupRawWebsocketClient(serverPath); ws.writeFrame(frame1); ws.writeFrame(frame2); ws.writeFrame(frame3); await(5, TimeUnit.SECONDS); assertEquals("Server did not combine continuation frames correctly", largeMessage, serverReceivedMessage.get()); }
@Test public void testCombineTextFrameSockJs() throws InterruptedException { String serverPath = "/text-combine-sockjs"; setupSockJsServer(serverPath, this::echoRequest); List<Buffer> receivedMessages = new ArrayList<>(); WebSocket openedWebSocket = setupSockJsClient(serverPath, receivedMessages); Buffer largeMessage = Buffer.buffer("[\"" + TestUtils.randomAlphaString(30) + "\"]"); WebSocketFrame frame1 = new WebSocketFrameImpl(FrameType.TEXT, largeMessage.slice(0, 10).getByteBuf(), false); WebSocketFrame frame2 = WebSocketFrame.continuationFrame(largeMessage.slice(10, 20), false); WebSocketFrame frame3 = WebSocketFrame.continuationFrame(largeMessage.slice(20, largeMessage.length()), true); log.debug("Client sending " + frame1.textData()); openedWebSocket.writeFrame(frame1); log.debug("Client sending " + frame2.textData()); openedWebSocket.writeFrame(frame2); log.debug("Client sending " + frame3.textData()); openedWebSocket.writeFrame(frame3); await(5, TimeUnit.SECONDS); assertEquals("Client should have received 2 messages: the reply and the close.", 2, receivedMessages.size()); Buffer expectedReply = Buffer.buffer("a" + largeMessage.toString()); assertEquals("Client reply should have matched request", expectedReply, receivedMessages.get(0)); assertEquals("Final message should have been a close", SOCKJS_CLOSE_REPLY, receivedMessages.get(1)); }
@Test public void testCombineMultipleFramesIntoASingleMessage() throws Exception { socketHandler = () -> { return socket -> socket.handler(buf -> { assertEquals("Hello World", buf.toString()); testComplete(); }); }; startServers(); client.websocket("/test/400/8ne8e94a/websocket", ws -> { ws.writeFrame(io.vertx.core.http.WebSocketFrame.textFrame("[\"Hello", false)); ws.writeFrame(io.vertx.core.http.WebSocketFrame.continuationFrame(Buffer.buffer(" World\"]"), true)); ws.close(); }); await(); } }
@Test public void testSendWebsocketContinuationFrames() { // Use raw websocket transport client.websocket("/echo/websocket", ws -> { int size = 65535; Buffer buffer1 = TestUtils.randomBuffer(size); Buffer buffer2 = TestUtils.randomBuffer(size); ws.writeFrame(io.vertx.core.http.WebSocketFrame.binaryFrame(buffer1, false)); ws.writeFrame(io.vertx.core.http.WebSocketFrame.continuationFrame(buffer2, true)); Buffer received = Buffer.buffer(); ws.handler(buff -> { received.appendBuffer(buff); if (received.length() == size * 2) { testComplete(); } }); }); await(); }