In this release, we added support for HTTP client traces. We also fixed a large number of bugs that could lead to connection stalls, deadlocks and memory leaks. See the "Major Fixes" section for more details.
New Features
- http3: add support for client traces
net/http/httptrace.ClientTrace
: #4749. Thanks to @lRoccoon for the contribution!
Major Fixes
- fix accounting for lost RESET_STREAM frames in the stream, leading to potential connection stalls / deadlocks: #4804. Thanks to @Wondertan for reporting and testing the fix!
- fix memory leak when the connection ID is rotated when the CONNECTION_CLOSE packet is sent: #4852. Thanks to @MarcoPolo for debugging this issue and contributing a fix!
- http3: fix QUIC connection re-dialing logic: #4854, #4875, #4879
- trigger sending of a new packet when a MAX_DATA frame (connection-level flow control update) is queued: #4844
Transport.Close
was reworked: calls toTransport.Dial
are now canceled, and return the newly introducedErrTransportClosed
, as do calls toTransport.Listen
: #4883
Enhancements
- trace dropping of packets by the
Transport
when no server is set: #4789 - trace dropping of packets that the
Transport
doesn't send a stateless for: #4826 - drain received packets when the connection is closed: #4773
- add Prometheus metrics for sent and received packets: #4910
- reduce calls to
time.Now
all over the code base: #4731, #4885, #4886, #4906 - packetize DATA_BLOCKED frames in the same QUIC packet that caused us to block on connection-level flow control: #4845
- packetize STREAM_DATA_BLOCKED frames in the same QUIC packed that caused us to block on stream-level flow control: #4801
- we now don't enforce that only one
Transport
listens on any givennet.PacketConn
: #4851
Other Fixes
- drain the server's connection accept queue before returning
ErrClosed
fromAccept
: #4846. Thanks to @sukunrt for discovering this bug and providing very helpful reviews! - preserve the error returned from
SendStream.Write
if it is closed after is canceled: #4882 - fix race condition on concurrent calls to
Transport.Dial
andTransport.Close
: #4904 - qlog: fix logging of packet_in_flight on the metrics_updated event: #4895
- fix
errors.Is
error comparisons: #4824, #4825, #4877 - http3: fix race condition on concurrent calls to
http.Response.Body.Close
: #4798. Thanks to @RPRX for the contribution! - flowcontrol: reset the connection send window on 0-RTT rejection: #4764
- wait for connection to shut down when the Dial context is cancelled: #4872
- http3: the
http.Request.Body
is now properly closed on all code paths that return a non-nil
error: #4874 - NEW_CONNECTION_ID frames are now rejected when zero-length connection IDs are used, as required by the RFC: #4878
- the stream ID of STREAM_DATA_BLOCKED frames is now validated, as required by the RFC: #4836
- fix ECN markings of packets sent in GSO batches when the marking changes: #4835
- the AEAD used to calculate the Retry Integrity Tag is now created lazily, avoiding a panic on initialization when using Go 1.24 FIPS-only mode: #4916
- use a 24h maximum token age as default value for
Transport.MaxTokenAge
: #4763
Behind the Scenes
In the v0.48.0 release, we started migrating our test suite away from Ginkgo (tracking issue: #3652). This is an absolutely massive endeavor. Before we started, the number of LOC of Ginkgo tests was more than 41,000.
In this release, we're bringing this number down to less than 8,500 LOC: #4736, #4746, #4775, #4783, #4788, #4790, #4795, #4796, #4797, #4799, #4814, #4816, #4817, #4823, #4837, #4842, #4847, #4848, #4849, #4853, #4857, #4860, #4861, #4862, #4863, #4864, #4865, #4869, #4876, #4881, #4907.
There's still a lot of work ahead, but we'll hopefully be able to finish this item in the next couple of months.
Changelog
- fix arming of keep-alive timer after sending PMTUD probe packets by @marten-seemann in #4716
- README: add Flipt reverst by @markphelps in #4542
- closed_conn.go: avoid data race in handlePacket(). Fixes #4718. by @glycerine in #4720
- fix documentation for IP fragmentation socket options on Windows by @marten-seemann in #4724
- ci: update golangci-lint to v1.62.0 by @marten-seemann in #4725
- ci: simplify the go generate script by @marten-seemann in #4728
- use IP_PMTUDISC_PROBE instead of IP_PMTUDISC_DO on Linux by @marten-seemann in #4729
- flowcontrol: fix start of the flow-control auto-tuning period by @marten-seemann in #4730
- flowcontrol: avoid calling time.Now(), pass time as a function parameter by @marten-seemann in #4731
- logging: use code generation to generate the multiplexed tracers by @marten-seemann in #4677
- flowcontrol: fix timestamp used for receive window auto-tuning by @marten-seemann in #4735
- flowcontrol: rewrite tests, use require instead of Ginkgo by @marten-seemann in #4734
- ci: disable the unparam linter for tests by @marten-seemann in #4738
- enable DPLPMTUD on macOS dual-stack sockets by @marten-seemann in #4723
- remove the Token field from the StatelessResetError by @marten-seemann in #4740
- wait until handshaking connections have terminated when closing server by @marten-seemann in #4743
- build(deps): bump codecov/codecov-action from 4 to 5 by @dependabot in #4741
- qlog: simplify QLOGDIR test by using t.Setenv and t.TempDir by @marten-seemann in #4745
- migrate HTTP/3 integration tests away from Ginkgo by @marten-seemann in #4746
- fix documentation for ConnectionState.SupportsDatagrams by @marten-seemann in #4754
- migrate integration tests away from Ginkgo by @marten-seemann in #4736
- fix timeout integration tests on Windows by @marten-seemann in #4758
- introduce a test helper function to create a new UDP socket on localhost by @marten-seemann in #4756
- actually send 0-length connection IDs in integration test by @marten-seemann in #4757
- fix flaky multiplex integration test by @marten-seemann in #4760
- ci: use go test in integration tests by @marten-seemann in #4759
- improve stream limit 0-RTT integration test by @marten-seemann in #4761
- use a 24h maximum token age if Transport.MaxTokenAge is unset by @marten-seemann in #4763
- fix flaky non-QUIC packet multiplexing test by @marten-seemann in #4766
- migrate framer tests away from Ginkgo by @marten-seemann in #4775
- update GoMock to v0.5.0 by @marten-seemann in #4776
- flowcontrol: reset the connection send window when 0-RTT is rejected by @marten-seemann in #4764
- utils: remove unused now parameter from RTTStats.UpdateRTT by @marten-seemann in #4780
- ci: fix Codecov environment variables by @marten-seemann in #4786
- migrate the transport tests away from Ginkgo by @marten-seemann in #4783
- trace dropping of packets by the Transport when no server is set by @marten-seemann in #4789
- migrate the config tests away from Ginkgo by @marten-seemann in #4790
- remove unneeded Connection.GetVersion method by @marten-seemann in #4792
- wire: don't allocate an empty data slice for empty STREAM frames by @marten-seemann in #4794
- migrate the buffer pool tests away from Ginkgo by @marten-seemann in #4796
- migrate the TokenStore tests away from Ginkgo by @marten-seemann in #4795
- migrate platform-dependent UDP socket test code away from Ginkgo by @marten-seemann in #4797
- migrate the packet packer tests away from Ginkgo by @marten-seemann in #4788
- ci: disable SA1029 staticcheck (context key check) in tests by @marten-seemann in #4802
- http3: allow concurrent calls to Body.Close by @RPRX in #4798
- migrate the stream tests away from Ginkgo by @marten-seemann in #4799
- fix flaky MITM packet injection test by @marten-seemann in #4810
- fix flaky TestSendStreamLargeWrites by @marten-seemann in #4813
- migrate multiplexer tests away from Ginkgo by @marten-seemann in #4814
- don't generate empty STREAM frames in the send stream by @marten-seemann in #4812
- don't enqueue send stream for sending on duplicate Close calls by @marten-seemann in #4815
- fix accounting for lost RESET_STREAM frames in the send stream by @marten-seemann in #4804
- migrate the packet handler map tests away from Ginkgo by @marten-seemann in #4816
- fix flaky MITM packet corruption test by @marten-seemann in #4821
- migrate the send conn tests away from Ginkgo by @marten-seemann in #4817
- qerr: fix errors.Is for TransportError and ApplicationError by @marten-seemann in #4824
- fix errors.Is for StreamError and DatagramTooLargeError by @marten-seemann in #4825
- remove hardcoded maximum keep-alive period by @marten-seemann in #4827
- trace packets that the transport doesn't send a stateless reset for by @marten-seemann in #4826
- remove redundant bool return value from sendStream.popStreamFrame by @marten-seemann in #4828
- drain receivedPackets buffer on connection close by @MarcoPolo in #4773
- fix flaky TestSendStreamStopSending by @marten-seemann in #4832
- migrate the connection tests away from Ginkgo by @marten-seemann in #4823
- ackhandler: remove error return value of SentPacketHandler.ResetForRetry by @marten-seemann in #4834
- validate the stream ID of STREAM_DATA_BLOCKED frames by @marten-seemann in #4836
- fix GSO sending logic to respect ECN marking changes by @marten-seemann in #4835
- migrate the crypto stream tests away from Ginkgo by @marten-seemann in #4837
- fix flaky TestConnectionCongestionControl by @marten-seemann in #4839
- optimize packing of STREAM_DATA_BLOCKED frames by @marten-seemann in #4801
- migrate the closed connection tests away from Ginkgo by @marten-seemann in #4848
- migrate the crypto stream manager tests away from Ginkgo by @marten-seemann in #4847
- migrate the datagram queue tests away from Ginkgo by @marten-seemann in #4849
- reliably queue MAX_DATA frames by @marten-seemann in #4844
- optimize packetization of DATA_BLOCKED frames by @marten-seemann in #4845
- migrate the frame sorter tests away from Ginkgo by @marten-seemann in #4853
- drain server's accept queue before returning ErrClosed from Accept by @marten-seemann in #4846
- http3: keep QUIC connection after request context expires by @marten-seemann in #4854
- remove validation enforcing one Transport per net.PacketConn by @marten-seemann in #4851
- simplify generation of stateless reset tokens by @marten-seemann in #4858
- migrate the unpacker tests away from Ginkgo by @marten-seemann in #4842
- migrate the connection ID manager tests away from Ginkgo by @marten-seemann in #4860
- migrate the send queue tests away from Ginkgo by @marten-seemann in #4861
- ackhandler: migrate ack-eliciting and send mode tests away from Ginkgo by @marten-seemann in #4862
- ackhandler: migrate received packet history tests away from Ginkgo by @marten-seemann in #4863
- ackhandler: migrate received packet tracker tests away from Ginkgo by @marten-seemann in #4864
- ackhandler: migrate received packet handler tests away from Ginkgo by @marten-seemann in #4865
- use testing.T.TempDir and Setenv in QLOGDIR integration test by @marten-seemann in #4868
- ackhandler: migrate sent packet history tests away from Ginkgo by @marten-seemann in #4869
- wait for connection to shut down when the Dial context is cancelled by @marten-seemann in #4872
- refactor client dialing logic, move it into the Transport by @marten-seemann in #4859
- http3: close http.Request.Body on all non-nil error code paths by @marten-seemann in #4874
- http3: migrate the transport tests away from Ginkgo by @marten-seemann in #4857
- http3: fix errors.Is for the Error by @marten-seemann in #4877
- reject NEW_CONNECTION_ID frames when using zero-length connection IDs by @marten-seemann in #4878
- http3: migrate the error tests away from Ginkgo by @marten-seemann in #4876
- http3: fix connection re-dialing logic for non-QUIC errors by @marten-seemann in #4879
- http3: rename singleRoundTripper interface to clientConn by @marten-seemann in #4875
- http3: fix flaky TestTransportConnectionRedial by @marten-seemann in #4884
- ackhandler: avoid calling time.Now() when setting loss detection timer by @marten-seemann in #4885
- ackhandler: avoid calling time.Now() when generating ACK frame by @marten-seemann in #4886
- ackhandler: remove unneeded SetHandshakeConfirmed from SentPacketHandler by @marten-seemann in #4890
- ackhandler: migrate sentPacketHandler tests away from Ginkgo by @marten-seemann in #4881
- qlog: fix logging of packets_in_flight on the metrics_updated event by @marten-seemann in #4895
- ackhandler: fix ack of packet number ranges in sent packet handler tests by @marten-seemann in #4897
- add ErrTransportClosed and use it for Listen/Dial after transport close by @marten-seemann in #4883
- http3: fix flaky transport tests by @marten-seemann in #4900
- wire: implement frame classification into probing / non-probing by @marten-seemann in #4901
- remove unused member variable in the mtuDiscoverer by @marten-seemann in #4905
- avoid calling time.Now() in the MTU discoverer by @marten-seemann in #4906
- preserve error from cancelled SendStream during cancellation and closing by @marten-seemann in #4882
- fix race condition on concurrent use of Transport.Dial and Close by @marten-seemann in #4904
- fix flaky TestALPN integration test by @marten-seemann in #4909
- migrate the MTU discoverer tests away from Ginkgo by @marten-seemann in #4907
- fix memory leak on connection ID rotation when closing connection by @marten-seemann in #4852
- simply PTO probe packet sending logic by @marten-seemann in #4913
- clean up MTU probe packet sending logic by @marten-seemann in #4914
- metrics: add Prometheus metrics for sent and received packets by @marten-seemann in #4910
- handshake: lazily create the AEAD used for Retry by @juliens in #4916
New Contributors
- @markphelps made their first contribution in #4542
- @RPRX made their first contribution in #4798
Full Changelog: v0.48.2...v0.49.0