Releases: algorand/websocket
Introduce MaxHeaderSize for response reader + go1.17
- Dialer now has MaxHeaderSize parameter that limits size of HTTP headers to be reads.
- Upgraded to use go1.17
Change go version to 1.16
v1.4.5 update to use go 1.16
Fix write lock deadline handling
The existing code in go-algorand is using two go-routines for reading/writing and a separate go-routine for opening/closing the connections.
When a client connection becomes non-responsive ( i.e. the writer is not returning ), the current implementation tries to close the connection. However, per WebSocket specification, the client is supposed to send a Close message first.
The close message is being sent using the WriteControl
method, which is supposed to be able to run concurrently with WriteMessage
. However, both reaches Conn.write
where it attempt to acquire a writing lock.
Since the WriteMessage -> Conn.write
is stuck ( but the WriteControl
doesn't really know it's stuck indefinitely ), the WriteControl -> Conn.write
get blocks indefinitely as well.
Unlike the WriteMessage
, when calling WriteControl
, we provide a deadline : a timestamp after which we don't care if the message was actually sent. In this PR, I have added handling that would limit the time the Conn.write
would wait to that deadline.
From spec perspective, it would be a violation of the WebSocket protocol; however, given that the other party is no longer responsive, a successful writing of a Close message is not possible, it would probably be just fine.
flush the connection when writing control messages
flush the connection when writing control messages
Fix a leaky go-routine on server side connections
Fix a leaky go-routine on server side connections.
The Upgrader.Upgrade method in the server.go was not shutting down the connection cleanly when it had write errors right after the connection was established. This codepath is expected when a non-websocket aware client is trying to connect to the server.
Instead of calling the CloseWithoutFlush, the Upgrader.Upgrade method was closing the underlying network connection ( correctly ), and returning, potentially leaving the flush goroutine abandoned.