Affects: \<5.3.6>
When setting server ping in Spring WebSocket, a text packet (opcode 1) with payload '\n' (0xA) is sent to the client. As a result the client doesn't understand the packet and doesn't send pong. I think the packet opcode should be 0x9 (ping).
Background info:
There was also another issue: ping sent by client does not update session timeout (doesn't push timeout timestamp further). I'm getting session expiration despite of client sending pings. But because of this problem, I'm now trying out server pings.
My session maximum idle interval is 30 seconds.
I'm establishing the session through a separate REST login endpoint. I use the received session cookie in the header when establishing a WebSocket connection. I've tried using embedded Hazelcast session repository and embedded Redis, too.
This is my WebSocket configuration:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSessionWebSocketMessageBrokerConfigurer<Session> {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
ThreadPoolTaskScheduler pingScheduler = new ThreadPoolTaskScheduler();
pingScheduler.setPoolSize(1);
pingScheduler.setThreadNamePrefix("wss-heartbeat-thread-");
pingScheduler.initialize();
config.enableSimpleBroker("/topic").setHeartbeatValue(new long[]{10000, 0}).setTaskScheduler(pingScheduler);
config.setApplicationDestinationPrefixes("/messages");
config.setUserDestinationPrefix("/user");
}
@Override
protected void configureStompEndpoints(StompEndpointRegistry registry)
{
registry.addEndpoint("/stomp").withSockJS();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
super.configureClientInboundChannel(registration);
registration.interceptors(new TopicSubscriptionInterceptor());
}
}
Comment From: rstoyanchev
What is the client, and is it possible to provide a repro project?
Comment From: mmikkone
Unfortenately repro project is not possible, because I have a deadline and I've already moved on to embedded ActiveMQ which seems to fulfill our needs.
The client was a python client using websockets.py and stomper.py. I verified the issue by debugging the python client and WireShark.
-Marko
ke 26. toukokuuta 2021 klo 12.27 Rossen Stoyanchev @.***> kirjoitti:
What is the client, and is it possible to provide a repro project?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/spring-projects/spring-framework/issues/26922#issuecomment-848617475, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEWFCVYDWCOG3TDNKLCTPITTPS5JHANCNFSM44QTXU7A .
Comment From: rstoyanchev
The heartbeat is defined in the protocol as an EOL character, and the BNF section says that's an optional CR (0x13) followed by LF (0x10). I'm not sure where you get that it should be 0x9 which is HT (horizontal tab).
We send \n
which should be fine according to the protocol. It works with the stomp.js client and our own Java STOMP client. We also use the same codecs to parse heartbeats from and external brokers and from clients, which hasn't brought up any issues. Hence my question about which client you experience this with.
As far as I can see ActiveMQ sends a \n
character as well. Do you know why that has made a difference?
Comment From: rstoyanchev
Also looking to version 1.1 of the protocol, in case the client is built for that, it says a single newline byte.
Comment From: mmikkone
I was under impression that setting a heartbeat sets a keepalive mechanism for the underlying WebSocket: https://datatracker.ietf.org/doc/html/rfc6455#section-5.5.2
Marko Lähettäjä
Comment From: rstoyanchev
STOMP has its own heartbeat mechanism which is at a level above the transport (WebSocket, TCP). I'm closing this as there is not enough information to understand the root cause of the issue.