-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
Describe the bug
WebSocketClient takes in a connectTimeout parameter. This parameter is used for the initial socket connection, but not when setting up the websocket connection. Poor network connectivity may mean we can set up the socket connection but not the websocket, leading to scenarios where connectBlocking blocks indefinitely.
To Reproduce
I ran this test on a Debian 10 system, using iptables to simulate the poor connectivity condition.
- Set up iptables firewall rules to begin dropping TCP traffic after six packets for a connection have been transferred:
sudo iptables -F INPUT
# Allow direct SSH access
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow pings
sudo iptables -A INPUT -p icmp -j ACCEPT
# Allow all DNS lookups
sudo iptables -A INPUT -p udp --source-port 53 -j ACCEPT
# For all other connections, only allow the first six packets (both directions considered) to pass
sudo iptables -A INPUT -m connbytes --connbytes-mode packets --connbytes-dir both ! --connbytes 6 -j ACCEPT
# Drop all other traffic
sudo iptables -A INPUT --in-interface eth0 -j DROP
- Compile and run this sample: https://github.com/ysi-camerona/java-websocket-bug-feb-9-2024
- Observe that the graceful client (client with a fix to respect connectTimeout for the websocket) fails after five seconds, whereas the default client blocks indefinitely
Example application to reproduce the issue
https://github.com/ysi-camerona/java-websocket-bug-feb-9-2024
Expected behavior
I would have expected that if connectBlocking() is called, and connectTimeout has elapsed before onOpen(ServerHandshake) is called, connectBlocking would return false.
Debug log
Logs from the sample application:
INFO | 2024-02-09 17:05:41 | main | WebsocketConnectionTest | 21 | Graceful client - connecting with 5000 ms timeout
INFO | 2024-02-09 17:05:42 | WebSocketConnectReadThread-9 | GracefulTimeoutClient | 53 | Set socket timeout to 5000 ms
INFO | 2024-02-09 17:05:47 | WebSocketConnectReadThread-9 | GracefulTimeoutClient | 41 | onError called
INFO | 2024-02-09 17:05:47 | WebSocketWriteThread-10 | GracefulTimeoutClient | 36 | onClose called
INFO | 2024-02-09 17:05:47 | main | WebsocketConnectionTest | 23 | Graceful client - finished connecting, result: false
INFO | 2024-02-09 17:05:47 | main | WebsocketConnectionTest | 25 | Graceful client - closed connection
INFO | 2024-02-09 17:05:47 | main | WebsocketConnectionTest | 30 | Default client - connecting with 5000 ms timeout
Nothing else had been logged by 2024-02-09 17:10:00.
Environment:
- Version used: Java-Websocket 1.5.3, 1.5.5, 1.5.6
- Java version: 1.8.0_332
Additional context
GracefulTimeoutClient shows a potential fix for this: set the socket SO timeout to the user-defined value in onSetSSLParameters, then set it back to zero after the websocket has connected.