A zero value for the Conn.WriteControl deadline specifies no timeout,
but the feature was implemented as a very long timeout (1000 hours).
This PR updates the code to use no timeout when the deadline is zero.
See the discussion in #895 for more details.
The package ignored errors from net.Conn Set*Deadline in a few places.
Update the package to return these errors to the caller.
Ignore all other errors reported by errcheck. These errors are safe to
ignore because
- The function is making a best effort to cleanup while handling another
error.
- The function call is guaranteed to succeed.
- The error is ignored in a test.
See https://go.dev/issue/45729.
- Remove hideTempError
The hideTempError function was used to prevent connection methods from
returning a net.Error with Temporary() == true.
Connection methods do not support retry after returning any net.Error,
including errors with Temporary() == true.
Presumably hideTempError was used to prevent applications from
futilely retrying connection method calls on temporary errors.
The hideTempError function is not needed now that net.Error
Temporary() is deprecated.
- Remove use of the deprecated net.Error Temporary() method in the
default ping handler by ignoring all errors returned from
WriteControl. Ignoring errors allows the application to continue
reading messages after a write error and is consistent with how the
default close handler calls WriteControl.
A zero value for the Conn.WriteControl deadline specifies no timeout,
but the feature was implemented as a very long timeout (1000 hours).
This PR updates the code to use no timeout when the deadline is zero.
See the discussion in #895 for more details.
The 666c197 added an error handling in `SetCloseHandler()` and peer
stops getting `CloseError` when network issue like `write: broken
pipe` happens because the close handle returns the error.
Hence this patch changes to skip network error handling.
<!--
For Work In Progress Pull Requests, please use the Draft PR feature,
see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for
further details.
For a timely review/response, please avoid force-pushing additional
commits if your PR already received reviews or comments.
Before submitting a Pull Request, please ensure that you have:
- 📖 Read the Contributing guide:
https://github.com/gorilla/.github/blob/main/CONTRIBUTING.md
- 📖 Read the Code of Conduct:
https://github.com/gorilla/.github/blob/main/CODE_OF_CONDUCT.md
- Provide tests for your changes.
- Use descriptive commit messages.
- Comment your code where appropriate.
- Squash your commits
- Update any related documentation.
- Add gorilla/pull-request-reviewers as a Reviewer
-->
## What type of PR is this? (check all applicable)
- [ ] Refactor
- [ ] Feature
- [x] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
- [ ] Go Version Update
- [ ] Dependency Update
## Description
Noticed a change in default close handler from 1.5.0 to 1.5.1
1.5.1 Now returns the error from `WriteControl` with `CloseMessage`
type. However this results in ErrCloseSent returned if the connection
initiated the close handshake. This is normally correct as the
connection should not be able to write after a close handshake is
initiated, except when calling the close handler. in that case nil
should be returned so that `advanceFrame()` can return the actual close
message.
## Related Tickets & Documents
## Added/updated tests?
- [x] Yes
- [ ] No, and this is why: _please replace this line with details on why
tests
have not been included_
- [ ] I need help with writing tests
## Run verifications and test
- [ ] `make verify` is passing (fails with `GO-2023-2186 Incorrect
detection of reserved device names on Windows in path/filepath` that is
unrelated to this change)
- [x] `make test` is passing
Co-authored-by: Corey Daley <cdaley@redhat.com>
Using empty struct for signaling is more idiomatic
compared to booleans because users might wonder
what happens on false or true. Empty struct removes
this problem.
There is also a side benefit of occupying less memory
but it should be negligible in this case.
This fix addresses a potential denial-of-service (DoS) vector that can cause an integer overflow in the presence of malicious WebSocket frames.
The fix adds additional checks against the remaining bytes on a connection, as well as a test to prevent regression.
Credit to Max Justicz (https://justi.cz/) for discovering and reporting this, as well as providing a robust PoC and review.
* build: go.mod to go1.12
* bugfix: fix DoS vector caused by readLimit bypass
* test: update TestReadLimit sub-test
* bugfix: payload length 127 should read bytes as uint64
* bugfix: defend against readLength overflows
Fix bug where connection did not return the write buffer to the pool
after a write error. Add test for the same.
Rename messsageWriter.fatal method to endMessage and consolidate all
message cleanup code there. This ensures that the buffer is returned to
pool on all code paths.
Rename Conn.prepMessage to beginMessage for symmetry with endMessage.
Move some duplicated code at calls to prepMessage to beginMessage.
Bonus improvement: Adjust message and buffer size in TestWriteBufferPool
to test that pool works with fragmented messages.
Add WriteBufferPool to Dialer and Upgrader. This field specifies a pool
to use for write operations on a connection. Use of the pool can reduce
memory use when there is a modest write volume over a large number of
connections.
Use larger of hijacked buffer and buffer allocated for connection (if
any) as buffer for building handshake response. This decreases possible
allocations when building the handshake response.
Modify bufio reuse test to call Upgrade instead of the internal
newConnBRW. Move the test from conn_test.go to server_test.go because
it's a serer test.
Update newConn and newConnBRW:
- Move the bufio "hacks" from newConnBRW to separate functions and call
these functions directly from Upgrade.
- Rename newConn to newTestConn and move to conn_test.go. Shorten
argument list to common use case.
- Rename newConnBRW to newConn.
- Add pool code to newConn.
The documentation sometimes used the term "frame" when referring to
single frame control messages. Use the term "message" for consistency
in the documentation and to hide a detail that most application
programmers do not need to know about.
Return empty message for CloseNoStatusReceived. This status indicates
that the message is empty, so make it so. Because it's illegal to send
CloseNoStatusReceived, this change should not break a correct
application.
Reuse the buffer backing the bufio.Writer returned from hijack if that
buffer is large enough to be generally useful and
Upgrader.WriteBufferSize == 0.
Update the logic for reusing bufio.Reader returned from hijack to match
the logic for bufio.Reader: The buffer backing the reader must be
sufficiently large to be generally useful and Upgrader.ReadBufferSize ==
0.
Improve the documentation for ReadBufferSize and WriterBufferSize in
Dialer and Upgrader.
Change the default compression level to 1. This level is faster and uses
less memory.
Add Conn.SetCompressionLevel API to allow applications to tune
compression on a per message basis.