Skip to content

Commit f1e406c

Browse files
committed
Fix handling of empty payload Pong message on Jetty
Issue: SPR-12727
1 parent c8a4d16 commit f1e406c

File tree

2 files changed

+80
-6
lines changed

2 files changed

+80
-6
lines changed

spring-websocket/src/main/java/org/springframework/web/socket/adapter/jetty/JettyWebSocketHandlerAdapter.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.web.socket.adapter.jetty;
1818

19+
import java.nio.ByteBuffer;
20+
1921
import org.apache.commons.logging.Log;
2022
import org.apache.commons.logging.LogFactory;
2123
import org.eclipse.jetty.websocket.api.Session;
@@ -36,6 +38,7 @@
3638
import org.springframework.web.socket.WebSocketHandler;
3739
import org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator;
3840

41+
3942
/**
4043
* Adapts {@link WebSocketHandler} to the Jetty 9 WebSocket API.
4144
*
@@ -45,8 +48,11 @@
4548
@WebSocket
4649
public class JettyWebSocketHandlerAdapter {
4750

51+
private static final ByteBuffer EMPTY_PAYLOAD = ByteBuffer.wrap(new byte[0]);
52+
4853
private static final Log logger = LogFactory.getLog(JettyWebSocketHandlerAdapter.class);
4954

55+
5056
private final WebSocketHandler webSocketHandler;
5157

5258
private final JettyWebSocketSession wsSession;
@@ -96,7 +102,8 @@ public void onWebSocketBinary(byte[] payload, int offset, int length) {
96102
@OnWebSocketFrame
97103
public void onWebSocketFrame(Frame frame) {
98104
if (OpCode.PONG == frame.getOpCode()) {
99-
PongMessage message = new PongMessage(frame.getPayload());
105+
ByteBuffer payload = frame.getPayload() != null ? frame.getPayload() : EMPTY_PAYLOAD;
106+
PongMessage message = new PongMessage(payload);
100107
try {
101108
this.webSocketHandler.handleMessage(this.wsSession, message);
102109
}

spring-websocket/src/test/java/org/springframework/web/socket/WebSocketIntegrationTests.java

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,8 +17,14 @@
1717
package org.springframework.web.socket;
1818

1919

20+
import static org.junit.Assert.*;
21+
2022
import java.net.URI;
23+
import java.util.ArrayList;
2124
import java.util.Arrays;
25+
import java.util.List;
26+
import java.util.concurrent.CountDownLatch;
27+
import java.util.concurrent.TimeUnit;
2228

2329
import org.junit.Test;
2430
import org.junit.runner.RunWith;
@@ -32,10 +38,10 @@
3238
import org.springframework.web.socket.config.annotation.EnableWebSocket;
3339
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
3440
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
41+
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
3542
import org.springframework.web.socket.handler.TextWebSocketHandler;
3643
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
3744

38-
import static org.junit.Assert.*;
3945

4046
/**
4147
* Client and server-side WebSocket integration tests.
@@ -67,6 +73,24 @@ public void subProtocolNegotiation() throws Exception {
6773
URI url = new URI(getWsBaseUrl() + "/ws");
6874
WebSocketSession session = this.webSocketClient.doHandshake(new TextWebSocketHandler(), headers, url).get();
6975
assertEquals("foo", session.getAcceptedProtocol());
76+
session.close();
77+
}
78+
79+
// SPR-12727
80+
81+
@Test
82+
public void unsolicitedPongWithEmptyPayload() throws Exception {
83+
TestWebSocketHandler serverHandler = this.wac.getBean(TestWebSocketHandler.class);
84+
serverHandler.setWaitMessageCount(1);
85+
86+
String url = getWsBaseUrl() + "/ws";
87+
WebSocketSession session = this.webSocketClient.doHandshake(new AbstractWebSocketHandler() {}, url).get();
88+
session.sendMessage(new PongMessage());
89+
90+
serverHandler.await();
91+
assertNull(serverHandler.getTransportError());
92+
assertEquals(1, serverHandler.getReceivedMessages().size());
93+
assertEquals(PongMessage.class, serverHandler.getReceivedMessages().get(0).getClass());
7094
}
7195

7296

@@ -84,8 +108,51 @@ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
84108
}
85109

86110
@Bean
87-
public TextWebSocketHandler handler() {
88-
return new TextWebSocketHandler();
111+
public TestWebSocketHandler handler() {
112+
return new TestWebSocketHandler();
113+
}
114+
115+
}
116+
117+
private static class TestWebSocketHandler extends AbstractWebSocketHandler {
118+
119+
private List<WebSocketMessage> receivedMessages = new ArrayList<>();
120+
121+
private int waitMessageCount;
122+
123+
private final CountDownLatch latch = new CountDownLatch(1);
124+
125+
private Throwable transportError;
126+
127+
128+
public void setWaitMessageCount(int waitMessageCount) {
129+
this.waitMessageCount = waitMessageCount;
130+
}
131+
132+
public List<WebSocketMessage> getReceivedMessages() {
133+
return this.receivedMessages;
134+
}
135+
136+
public Throwable getTransportError() {
137+
return this.transportError;
138+
}
139+
140+
@Override
141+
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
142+
this.receivedMessages.add(message);
143+
if (this.receivedMessages.size() >= this.waitMessageCount) {
144+
this.latch.countDown();
145+
}
146+
}
147+
148+
@Override
149+
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
150+
this.transportError = exception;
151+
this.latch.countDown();
152+
}
153+
154+
public void await() throws InterruptedException {
155+
this.latch.await(5, TimeUnit.SECONDS);
89156
}
90157
}
91158

0 commit comments

Comments
 (0)