Skip to content

Commit c8299de

Browse files
authored
Merge pull request #1960 from bjlaub/fix-websocket-text-size-limits
[UNDERTOW-2770] websocket BufferedTextMessage correctly respects max size
2 parents 0b2d5b4 + 20ee39d commit c8299de

2 files changed

Lines changed: 90 additions & 0 deletions

File tree

‎core/src/main/java/io/undertow/websockets/core/BufferedTextMessage.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ public void handleEvent(StreamSourceFrameChannel channel) {
141141
}
142142
return;
143143
}
144+
checkMaxSize(channel, res);
144145
if (!buffer.hasRemaining()) {
145146
buffer.flip();
146147
data.write(buffer);

‎core/src/test/java/io/undertow/websockets/core/protocol/AbstractWebSocketServerTest.java‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,46 @@
5858
@HttpOneOnly
5959
public class AbstractWebSocketServerTest {
6060

61+
private static final long sizeLimitedMaxSize = 1024 * 32;
62+
private static final String largeText = "a".repeat((int) sizeLimitedMaxSize + 1024);
63+
64+
@Test
65+
public void testTextSizeLimited() throws Exception {
66+
if (getVersion() == WebSocketVersion.V00) {
67+
// ignore 00 tests for now
68+
return;
69+
}
70+
final AtomicBoolean connected = new AtomicBoolean(false);
71+
DefaultServer.setRootHandler(new WebSocketProtocolHandshakeHandler(new WebSocketConnectionCallback() {
72+
@Override
73+
public void onConnect(final WebSocketHttpExchange exchange, final WebSocketChannel channel) {
74+
connected.set(true);
75+
channel.getReceiveSetter().set(new AbstractReceiveListener() {
76+
@Override
77+
protected long getMaxTextBufferSize() {
78+
return sizeLimitedMaxSize;
79+
}
80+
81+
@Override
82+
protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage message) throws IOException {
83+
String string = message.getData();
84+
WebSockets.sendText(string, channel, null);
85+
}
86+
});
87+
channel.resumeReceives();
88+
}
89+
}));
90+
91+
final FutureResult<?> latch = new FutureResult();
92+
WebSocketTestClient client = new WebSocketTestClient(getVersion(), new URI("ws://" + NetworkUtils.formatPossibleIpv6Address(DefaultServer.getHostAddress("default")) + ":" + DefaultServer.getHostPort("default") + "/"));
93+
client.connect();
94+
// we expect a CloseWebSocketFrame on the response with an error about the message being too big
95+
CloseMessage expectedClose = new CloseMessage(CloseMessage.MSG_TOO_BIG, WebSocketMessages.MESSAGES.messageToBig(sizeLimitedMaxSize));
96+
client.send(new TextWebSocketFrame(Unpooled.copiedBuffer(largeText, CharsetUtil.US_ASCII)), new FrameChecker(CloseWebSocketFrame.class, expectedClose.toByteBuffer().array(), latch));
97+
latch.getIoFuture().get();
98+
client.destroy();
99+
}
100+
61101
@Test
62102
public void testText() throws Exception {
63103
if (getVersion() == WebSocketVersion.V00) {
@@ -93,6 +133,55 @@ protected void onFullTextMessage(WebSocketChannel channel, BufferedTextMessage m
93133
client.destroy();
94134
}
95135

136+
@Test
137+
public void testBinarySizeLimited() throws Exception {
138+
if (getVersion() == WebSocketVersion.V00) {
139+
// ignore 00 tests for now
140+
return;
141+
}
142+
final AtomicBoolean connected = new AtomicBoolean(false);
143+
DefaultServer.setRootHandler(new WebSocketProtocolHandshakeHandler(new WebSocketConnectionCallback() {
144+
@Override
145+
public void onConnect(final WebSocketHttpExchange exchange, final WebSocketChannel channel) {
146+
connected.set(true);
147+
channel.getReceiveSetter().set(new AbstractReceiveListener() {
148+
@Override
149+
protected long getMaxBinaryBufferSize() {
150+
return sizeLimitedMaxSize;
151+
}
152+
153+
@Override
154+
protected void onFullBinaryMessage(WebSocketChannel channel, BufferedBinaryMessage message) throws IOException {
155+
final Pooled<ByteBuffer[]> data = message.getData();
156+
WebSockets.sendBinary(data.getResource(), channel, new WebSocketCallback<Void>() {
157+
@Override
158+
public void complete(WebSocketChannel channel, Void context) {
159+
data.close();
160+
}
161+
162+
@Override
163+
public void onError(WebSocketChannel channel, Void context, Throwable throwable) {
164+
data.close();
165+
}
166+
});
167+
}
168+
});
169+
channel.resumeReceives();
170+
}
171+
}));
172+
173+
final FutureResult latch = new FutureResult();
174+
final byte[] payload = largeText.getBytes();
175+
176+
WebSocketTestClient client = new WebSocketTestClient(getVersion(), new URI("ws://" + NetworkUtils.formatPossibleIpv6Address(DefaultServer.getHostAddress("default")) + ":" + DefaultServer.getHostPort("default") + "/"));
177+
client.connect();
178+
// we expect a CloseWebSocketFrame on the response with an error about the message being too big
179+
CloseMessage expectedClose = new CloseMessage(CloseMessage.MSG_TOO_BIG, WebSocketMessages.MESSAGES.messageToBig(sizeLimitedMaxSize));
180+
client.send(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(payload)), new FrameChecker(CloseWebSocketFrame.class, expectedClose.toByteBuffer().array(), latch));
181+
latch.getIoFuture().get();
182+
client.destroy();
183+
}
184+
96185
@Test
97186
public void testBinary() throws Exception {
98187
if (getVersion() == WebSocketVersion.V00) {

0 commit comments

Comments
 (0)