jetty.project
jetty.project copied to clipboard
Improve WebSocket connection closing
Jetty version(s) 12
Description The analysis to fix #11581 showed the following:
WebSocket closes the EndPoint too early, namely when it has received a CLOSE frame and it has sent one.
Instead, it should wait to read -1 after receiving the CLOSE frame, and close the EndPoint after it has sent one.
When WebSocket is carried over HTTP/2, the CLOSE frame is carried in a DATA frame with endStream=false, followed by an empty DATA frame with endStream=true.
If the HTTP2StreamEndPoint is closed too early, it results in the empty DATA frame with endStream=true to be seen as an invalid frame arriving after the HTTP2Stream has been closed, resulting in a RST_STREAM being sent to the other peer.
The other peer then receives: a DATA frame containing the WebSocket CLOSE frame, then the empty DATA frame, then a RST_STREAM frame. The DATA frame containing the WebSocket CLOSE frame typically triggers the WebSocket implementation to read from the EndPoint in a different thread, but the read may be delayed. If the read is delayed, the RST_STREAM frame may be processed, which drains the DATA frames, so that the WebSocket implementation only reads an unexpected -1, rather than the WebSocket CLOSE frame.
This is a general issue for protocols carried over HTTP/2: they must read up to -1 before triggering the close of the EndPoint, despite the fact that a previous read signaled the protocol "end-of-data".