mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-04-04 21:57:44 +03:00
Update deps
This commit is contained in:
parent
4f3ce0cbae
commit
f42b7dad17
93 changed files with 4303 additions and 1673 deletions
187
vendor/github.com/quic-go/quic-go/README.md
generated
vendored
187
vendor/github.com/quic-go/quic-go/README.md
generated
vendored
|
@ -5,28 +5,185 @@
|
|||
[](https://pkg.go.dev/github.com/quic-go/quic-go)
|
||||
[](https://codecov.io/gh/quic-go/quic-go/)
|
||||
|
||||
quic-go is an implementation of the QUIC protocol ([RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000), [RFC 9001](https://datatracker.ietf.org/doc/html/rfc9001), [RFC 9002](https://datatracker.ietf.org/doc/html/rfc9002)) in Go, including the Unreliable Datagram Extension ([RFC 9221](https://datatracker.ietf.org/doc/html/rfc9221)) and Datagram Packetization Layer Path MTU
|
||||
Discovery (DPLPMTUD, [RFC 8899](https://datatracker.ietf.org/doc/html/rfc8899)). It has support for HTTP/3 ([RFC 9114](https://datatracker.ietf.org/doc/html/rfc9114)), including QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)).
|
||||
quic-go is an implementation of the QUIC protocol ([RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000), [RFC 9001](https://datatracker.ietf.org/doc/html/rfc9001), [RFC 9002](https://datatracker.ietf.org/doc/html/rfc9002)) in Go. It has support for HTTP/3 ([RFC 9114](https://datatracker.ietf.org/doc/html/rfc9114)), including QPACK ([RFC 9204](https://datatracker.ietf.org/doc/html/rfc9204)).
|
||||
|
||||
In addition to these base RFCs, it also implements the following RFCs:
|
||||
* Unreliable Datagram Extension ([RFC 9221](https://datatracker.ietf.org/doc/html/rfc9221))
|
||||
* Datagram Packetization Layer Path MTU Discovery (DPLPMTUD, [RFC 8899](https://datatracker.ietf.org/doc/html/rfc8899))
|
||||
* QUIC Version 2 ([RFC 9369](https://datatracker.ietf.org/doc/html/rfc9369))
|
||||
|
||||
In addition to the RFCs listed above, it currently implements the [IETF QUIC draft-29](https://tools.ietf.org/html/draft-ietf-quic-transport-29). Support for draft-29 will eventually be dropped, as it is phased out of the ecosystem.
|
||||
|
||||
## Guides
|
||||
This repository provides both a QUIC implementation, located in the `quic` package, as well as an HTTP/3 implementation, located in the `http3` package.
|
||||
|
||||
*We currently support Go 1.19.x and Go 1.20.x*
|
||||
## Using QUIC
|
||||
|
||||
Running tests:
|
||||
### Running a Server
|
||||
|
||||
go test ./...
|
||||
The central entry point is the `quic.Transport`. A transport manages QUIC connections running on a single UDP socket. Since QUIC uses Connection IDs, it can demultiplex a listener (accepting incoming connections) and an arbitrary number of outgoing QUIC connections on the same UDP socket.
|
||||
|
||||
### QUIC without HTTP/3
|
||||
```go
|
||||
udpConn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: 1234})
|
||||
// ... error handling
|
||||
tr := quic.Transport{
|
||||
Conn: udpConn,
|
||||
}
|
||||
ln, err := tr.Listen(tlsConf, quicConf)
|
||||
// ... error handling
|
||||
go func() {
|
||||
for {
|
||||
conn, err := ln.Accept()
|
||||
// ... error handling
|
||||
// handle the connection, usually in a new Go routine
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Take a look at [this echo example](example/echo/echo.go).
|
||||
The listener `ln` can now be used to accept incoming QUIC connections by (repeatedly) calling the `Accept` method (see below for more information on the `quic.Connection`).
|
||||
|
||||
## Usage
|
||||
As a shortcut, `quic.Listen` and `quic.ListenAddr` can be used without explicitly initializing a `quic.Transport`:
|
||||
|
||||
```
|
||||
ln, err := quic.Listen(udpConn, tlsConf, quicConf)
|
||||
```
|
||||
|
||||
When using the shortcut, it's not possible to reuse the same UDP socket for outgoing connections.
|
||||
|
||||
### Running a Client
|
||||
|
||||
As mentioned above, multiple outgoing connections can share a single UDP socket, since QUIC uses Connection IDs to demultiplex connections.
|
||||
|
||||
```go
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // 3s handshake timeout
|
||||
defer cancel()
|
||||
conn, err := tr.Dial(ctx, <server address>, <tls.Config>, <quic.Config>)
|
||||
// ... error handling
|
||||
```
|
||||
|
||||
As a shortcut, `quic.Dial` and `quic.DialAddr` can be used without explictly initializing a `quic.Transport`:
|
||||
|
||||
```go
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) // 3s handshake timeout
|
||||
defer cancel()
|
||||
conn, err := quic.Dial(ctx, conn, <server address>, <tls.Config>, <quic.Config>)
|
||||
```
|
||||
|
||||
Just as we saw before when used a similar shortcut to run a server, it's also not possible to reuse the same UDP socket for other outgoing connections, or to listen for incoming connections.
|
||||
|
||||
### Using a QUIC Connection
|
||||
|
||||
#### Accepting Streams
|
||||
|
||||
QUIC is a stream-multiplexed transport. A `quic.Connection` fundamentally differs from the `net.Conn` and the `net.PacketConn` interface defined in the standard library. Data is sent and received on (unidirectional and bidirectional) streams (and, if supported, in [datagrams](#quic-datagrams)), not on the connection itself. The stream state machine is described in detail in [Section 3 of RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-3).
|
||||
|
||||
Note: A unidirectional stream is a stream that the initiator can only write to (`quic.SendStream`), and the receiver can only read from (`quic.ReceiveStream`). A bidirectional stream (`quic.Stream`) allows reading from and writing to for both sides.
|
||||
|
||||
On the receiver side, streams are accepted using the `AcceptStream` (for bidirectional) and `AcceptUniStream` functions. For most user cases, it makes sense to call these functions in a loop:
|
||||
|
||||
```go
|
||||
for {
|
||||
str, err := conn.AcceptStream(context.Background()) // for bidirectional streams
|
||||
// ... error handling
|
||||
// handle the stream, usually in a new Go routine
|
||||
}
|
||||
```
|
||||
|
||||
These functions return an error when the underlying QUIC connection is closed.
|
||||
|
||||
#### Opening Streams
|
||||
|
||||
There are two slightly different ways to open streams, one synchronous and one (potentially) asynchronous. This API is necessary since the receiver grants us a certain number of streams that we're allowed to open. It may grant us additional streams later on (typically when existing streams are closed), but it means that at the time we want to open a new stream, we might not be able to do so.
|
||||
|
||||
Using the synchronous method `OpenStreamSync` for bidirectional streams, and `OpenUniStreamSync` for unidirectional streams, an application can block until the peer allows opening additional streams. In case that we're allowed to open a new stream, these methods return right away:
|
||||
|
||||
```go
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
str, err := conn.OpenStreamSync(ctx) // wait up to 5s to open a new bidirectional stream
|
||||
```
|
||||
|
||||
The asynchronous version never blocks. If it's currently not possible to open a new stream, it returns a `net.Error` timeout error:
|
||||
|
||||
```go
|
||||
str, err := conn.OpenStream()
|
||||
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
|
||||
// It's currently not possible to open another stream,
|
||||
// but it might be possible later, once the peer allowed us to do so.
|
||||
}
|
||||
```
|
||||
|
||||
These functions return an error when the underlying QUIC connection is closed.
|
||||
|
||||
#### Using Streams
|
||||
|
||||
Using QUIC streams is pretty straightforward. The `quic.ReceiveStream` implements the `io.Reader` interface, and the `quic.SendStream` implements the `io.Writer` interface. A bidirectional stream (`quic.Stream`) implements both these interfaces. Conceptually, a bidirectional stream can be thought of as the composition of two unidirectional streams in opposite directions.
|
||||
|
||||
Calling `Close` on a `quic.SendStream` or a `quic.Stream` closes the send side of the stream. On the receiver side, this will be surfaced as an `io.EOF` returned from the `io.Reader` once all data has been consumed. Note that for bidirectional streams, `Close` _only_ closes the send side of the stream. It is still possible to read from the stream until the peer closes or resets the stream.
|
||||
|
||||
In case the application wishes to abort sending on a `quic.SendStream` or a `quic.Stream` , it can reset the send side by calling `CancelWrite` with an application-defined error code (an unsigned 62-bit number). On the receiver side, this surfaced as a `quic.StreamError` containing that error code on the `io.Reader`. Note that for bidirectional streams, `CancelWrite` _only_ resets the send side of the stream. It is still possible to read from the stream until the peer closes or resets the stream.
|
||||
|
||||
Conversely, in case the application wishes to abort receiving from a `quic.ReceiveStream` or a `quic.Stream`, it can ask the sender to abort data transmission by calling `CancelRead` with an application-defined error code (an unsigned 62-bit number). On the receiver side, this surfaced as a `quic.StreamError` containing that error code on the `io.Writer`. Note that for bidirectional streams, `CancelWrite` _only_ resets the receive side of the stream. It is still possible to write to the stream.
|
||||
|
||||
A bidirectional stream is only closed once both the read and the write side of the stream have been either closed and reset. Only then the peer is granted a new stream according to the maximum number of concurrent streams configured via `quic.Config.MaxIncomingStreams`.
|
||||
|
||||
### Configuring QUIC
|
||||
|
||||
The `quic.Config` struct passed to both the listen and dial calls (see above) contains a wide range of configuration options for QUIC connections, incl. the ability to fine-tune flow control limits, the number of streams that the peer is allowed to open concurrently, keep-alives, idle timeouts, and many more. Please refer to the documentation for the `quic.Config` for details.
|
||||
|
||||
The `quic.Transport` contains a few configuration options that don't apply to any single QUIC connection, but to all connections handled by that transport. It is highly recommend to set the `StatelessResetToken`, which allows endpoints to quickly recover from crashes / reboots of our node (see [Section 10.3 of RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-10.3)).
|
||||
|
||||
### Closing a Connection
|
||||
|
||||
#### When the remote Peer closes the Connection
|
||||
|
||||
In case the peer closes the QUIC connection, all calls to open streams, accept streams, as well as all methods on streams immediately return an error. Users can use errors assertions to find out what exactly went wrong:
|
||||
|
||||
* `quic.VersionNegotiationError`: Happens during the handshake, if there is no overlap between our and the remote's supported QUIC versions.
|
||||
* `quic.HandshakeTimeoutError`: Happens if the QUIC handshake doesn't complete within the time specified in `quic.Config.HandshakeTimeout`.
|
||||
* `quic.IdleTimeoutError`: Happens after completion of the handshake if the connection is idle for longer than the minimum of both peers idle timeouts (as configured by `quic.Config.IdleTimeout`). The connection is considered idle when no stream data (and datagrams, if applicable) are exchanged for that period. The QUIC connection can be instructed to regularly send a packet to prevent a connection from going idle by setting `quic.Config.KeepAlive`. However, this is no guarantee that the peer doesn't suddenly go away (e.g. by abruptly shutting down the node or by crashing), or by a NAT binding expiring, in which case this error might still occur.
|
||||
* `quic.StatelessResetError`: Happens when the remote peer lost the state required to decrypt the packet. This requires the `quic.Transport.StatelessResetToken` to be configured by the peer.
|
||||
* `quic.TransportError`: Happens if when the QUIC protocol is violated. Unless the error code is `APPLICATION_ERROR`, this will not happen unless one of the QUIC stacks involved is misbehaving. Please open an issue if you encounter this error.
|
||||
* `quic.ApplicationError`: Happens when the remote decides to close the connection, see below.
|
||||
|
||||
#### Initiated by the Application
|
||||
|
||||
A `quic.Connection` can be closed using `CloseWithError`:
|
||||
|
||||
```go
|
||||
conn.CloseWithError(0x42, "error 0x42 occurred")
|
||||
```
|
||||
|
||||
Applications can transmit both an error code (an unsigned 62-bit number) as well as a UTF-8 encoded human-readable reason. The error code allows the receiver to learn why the connection was closed, and the reason can be useful for debugging purposes.
|
||||
|
||||
On the receiver side, this is surfaced as a `quic.ApplicationError`.
|
||||
|
||||
### QUIC Datagrams
|
||||
|
||||
Unreliable datagrams are a QUIC extension ([RFC 9221](https://datatracker.ietf.org/doc/html/rfc9221)) that is negotiated during the handshake. Support can be enabled by setting the `quic.Config.EnableDatagram` flag. Note that this doesn't guarantee that the peer also supports datagrams. Whether or not the feature negotiation succeeded can be learned from the `quic.ConnectionState.SupportsDatagrams` obtained from `quic.Connection.ConnectionState()`.
|
||||
|
||||
QUIC DATAGRAMs are a new QUIC frame type sent in QUIC 1-RTT packets (i.e. after completion of the handshake). Therefore, they're end-to-end encrypted and congestion-controlled. However, if a DATAGRAM frame is deemed lost by QUIC's loss detection mechanism, they are not automatically retransmitted.
|
||||
|
||||
Datagrams are sent using the `SendMessage` method on the `quic.Connection`:
|
||||
|
||||
```go
|
||||
conn.SendMessage([]byte("foobar"))
|
||||
```
|
||||
|
||||
And received using `ReceiveMessage`:
|
||||
|
||||
```go
|
||||
msg, err := conn.ReceiveMessage()
|
||||
```
|
||||
|
||||
Note that this code path is currently not optimized. It works for datagrams that are sent occasionally, but it doesn't achieve the same throughput as writing data on a stream. Please get in touch on issue #3766 if your use case relies on high datagram throughput, or if you'd like to help fix this issue. There are also some restrictions regarding the maximum message size (see #3599).
|
||||
|
||||
|
||||
|
||||
## Using HTTP/3
|
||||
|
||||
### As a server
|
||||
|
||||
See the [example server](example/main.go). Starting a QUIC server is very similar to the standard lib http in go:
|
||||
See the [example server](example/main.go). Starting a QUIC server is very similar to the standard library http package in Go:
|
||||
|
||||
```go
|
||||
http.Handle("/", http.FileServer(http.Dir(wwwDir)))
|
||||
|
@ -59,6 +216,16 @@ http.Client{
|
|||
| [v2ray-core](https://github.com/v2fly/v2ray-core) | A platform for building proxies to bypass network restrictions |  |
|
||||
| [YoMo](https://github.com/yomorun/yomo) | Streaming Serverless Framework for Geo-distributed System |  |
|
||||
|
||||
If you'd like to see your project added to this list, please send us a PR.
|
||||
|
||||
## Release Policy
|
||||
|
||||
quic-go always aims to support the latest two Go releases.
|
||||
|
||||
### Dependency on forked crypto/tls
|
||||
|
||||
Since the standard library didn't provide any QUIC APIs before the Go 1.21 release, we had to fork crypto/tls to add the required APIs ourselves: [qtls for Go 1.20](https://github.com/quic-go/qtls-go1-20) and [qtls for Go 1.19](https://github.com/quic-go/qtls-go1-19). This had led to a lot of pain in the Go ecosystem, and we're happy that we can rely on Go 1.21 going forward.
|
||||
|
||||
## Contributing
|
||||
|
||||
We are always happy to welcome new contributors! We have a number of self-contained issues that are suitable for first-time contributors, they are tagged with [help wanted](https://github.com/quic-go/quic-go/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22). If you have any questions, please feel free to reach out by opening an issue or leaving a comment.
|
||||
|
|
34
vendor/github.com/quic-go/quic-go/buffer_pool.go
generated
vendored
34
vendor/github.com/quic-go/quic-go/buffer_pool.go
generated
vendored
|
@ -51,18 +51,22 @@ func (b *packetBuffer) Release() {
|
|||
}
|
||||
|
||||
// Len returns the length of Data
|
||||
func (b *packetBuffer) Len() protocol.ByteCount {
|
||||
return protocol.ByteCount(len(b.Data))
|
||||
}
|
||||
func (b *packetBuffer) Len() protocol.ByteCount { return protocol.ByteCount(len(b.Data)) }
|
||||
func (b *packetBuffer) Cap() protocol.ByteCount { return protocol.ByteCount(cap(b.Data)) }
|
||||
|
||||
func (b *packetBuffer) putBack() {
|
||||
if cap(b.Data) != int(protocol.MaxPacketBufferSize) {
|
||||
panic("putPacketBuffer called with packet of wrong size!")
|
||||
if cap(b.Data) == protocol.MaxPacketBufferSize {
|
||||
bufferPool.Put(b)
|
||||
return
|
||||
}
|
||||
bufferPool.Put(b)
|
||||
if cap(b.Data) == protocol.MaxLargePacketBufferSize {
|
||||
largeBufferPool.Put(b)
|
||||
return
|
||||
}
|
||||
panic("putPacketBuffer called with packet of wrong size!")
|
||||
}
|
||||
|
||||
var bufferPool sync.Pool
|
||||
var bufferPool, largeBufferPool sync.Pool
|
||||
|
||||
func getPacketBuffer() *packetBuffer {
|
||||
buf := bufferPool.Get().(*packetBuffer)
|
||||
|
@ -71,10 +75,18 @@ func getPacketBuffer() *packetBuffer {
|
|||
return buf
|
||||
}
|
||||
|
||||
func getLargePacketBuffer() *packetBuffer {
|
||||
buf := largeBufferPool.Get().(*packetBuffer)
|
||||
buf.refCount = 1
|
||||
buf.Data = buf.Data[:0]
|
||||
return buf
|
||||
}
|
||||
|
||||
func init() {
|
||||
bufferPool.New = func() interface{} {
|
||||
return &packetBuffer{
|
||||
Data: make([]byte, 0, protocol.MaxPacketBufferSize),
|
||||
}
|
||||
bufferPool.New = func() any {
|
||||
return &packetBuffer{Data: make([]byte, 0, protocol.MaxPacketBufferSize)}
|
||||
}
|
||||
largeBufferPool.New = func() any {
|
||||
return &packetBuffer{Data: make([]byte, 0, protocol.MaxLargePacketBufferSize)}
|
||||
}
|
||||
}
|
||||
|
|
23
vendor/github.com/quic-go/quic-go/client.go
generated
vendored
23
vendor/github.com/quic-go/quic-go/client.go
generated
vendored
|
@ -43,7 +43,9 @@ type client struct {
|
|||
var generateConnectionIDForInitial = protocol.GenerateConnectionIDForInitial
|
||||
|
||||
// DialAddr establishes a new QUIC connection to a server.
|
||||
// It uses a new UDP connection and closes this connection when the QUIC connection is closed.
|
||||
// It resolves the address, and then creates a new UDP connection to dial the QUIC server.
|
||||
// When the QUIC connection is closed, this UDP connection is closed.
|
||||
// See Dial for more details.
|
||||
func DialAddr(ctx context.Context, addr string, tlsConf *tls.Config, conf *Config) (Connection, error) {
|
||||
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||
if err != nil {
|
||||
|
@ -61,7 +63,7 @@ func DialAddr(ctx context.Context, addr string, tlsConf *tls.Config, conf *Confi
|
|||
}
|
||||
|
||||
// DialAddrEarly establishes a new 0-RTT QUIC connection to a server.
|
||||
// It uses a new UDP connection and closes this connection when the QUIC connection is closed.
|
||||
// See DialAddr for more details.
|
||||
func DialAddrEarly(ctx context.Context, addr string, tlsConf *tls.Config, conf *Config) (EarlyConnection, error) {
|
||||
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
|
||||
if err != nil {
|
||||
|
@ -83,8 +85,8 @@ func DialAddrEarly(ctx context.Context, addr string, tlsConf *tls.Config, conf *
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
// DialEarly establishes a new 0-RTT QUIC connection to a server using a net.PacketConn using the provided context.
|
||||
// See DialEarly for details.
|
||||
// DialEarly establishes a new 0-RTT QUIC connection to a server using a net.PacketConn.
|
||||
// See Dial for more details.
|
||||
func DialEarly(ctx context.Context, c net.PacketConn, addr net.Addr, tlsConf *tls.Config, conf *Config) (EarlyConnection, error) {
|
||||
dl, err := setupTransport(c, tlsConf, false)
|
||||
if err != nil {
|
||||
|
@ -98,12 +100,15 @@ func DialEarly(ctx context.Context, c net.PacketConn, addr net.Addr, tlsConf *tl
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
// Dial establishes a new QUIC connection to a server using a net.PacketConn. If
|
||||
// the PacketConn satisfies the OOBCapablePacketConn interface (as a net.UDPConn
|
||||
// does), ECN and packet info support will be enabled. In this case, ReadMsgUDP
|
||||
// and WriteMsgUDP will be used instead of ReadFrom and WriteTo to read/write
|
||||
// packets.
|
||||
// Dial establishes a new QUIC connection to a server using a net.PacketConn.
|
||||
// If the PacketConn satisfies the OOBCapablePacketConn interface (as a net.UDPConn does),
|
||||
// ECN and packet info support will be enabled. In this case, ReadMsgUDP and WriteMsgUDP
|
||||
// will be used instead of ReadFrom and WriteTo to read/write packets.
|
||||
// The tls.Config must define an application protocol (using NextProtos).
|
||||
//
|
||||
// This is a convenience function. More advanced use cases should instantiate a Transport,
|
||||
// which offers configuration options for a more fine-grained control of the connection establishment,
|
||||
// including reusing the underlying UDP socket for multiple QUIC connections.
|
||||
func Dial(ctx context.Context, c net.PacketConn, addr net.Addr, tlsConf *tls.Config, conf *Config) (Connection, error) {
|
||||
dl, err := setupTransport(c, tlsConf, false)
|
||||
if err != nil {
|
||||
|
|
8
vendor/github.com/quic-go/quic-go/closed_conn.go
generated
vendored
8
vendor/github.com/quic-go/quic-go/closed_conn.go
generated
vendored
|
@ -16,13 +16,13 @@ type closedLocalConn struct {
|
|||
perspective protocol.Perspective
|
||||
logger utils.Logger
|
||||
|
||||
sendPacket func(net.Addr, *packetInfo)
|
||||
sendPacket func(net.Addr, packetInfo)
|
||||
}
|
||||
|
||||
var _ packetHandler = &closedLocalConn{}
|
||||
|
||||
// newClosedLocalConn creates a new closedLocalConn and runs it.
|
||||
func newClosedLocalConn(sendPacket func(net.Addr, *packetInfo), pers protocol.Perspective, logger utils.Logger) packetHandler {
|
||||
func newClosedLocalConn(sendPacket func(net.Addr, packetInfo), pers protocol.Perspective, logger utils.Logger) packetHandler {
|
||||
return &closedLocalConn{
|
||||
sendPacket: sendPacket,
|
||||
perspective: pers,
|
||||
|
@ -30,7 +30,7 @@ func newClosedLocalConn(sendPacket func(net.Addr, *packetInfo), pers protocol.Pe
|
|||
}
|
||||
}
|
||||
|
||||
func (c *closedLocalConn) handlePacket(p *receivedPacket) {
|
||||
func (c *closedLocalConn) handlePacket(p receivedPacket) {
|
||||
c.counter++
|
||||
// exponential backoff
|
||||
// only send a CONNECTION_CLOSE for the 1st, 2nd, 4th, 8th, 16th, ... packet arriving
|
||||
|
@ -58,7 +58,7 @@ func newClosedRemoteConn(pers protocol.Perspective) packetHandler {
|
|||
return &closedRemoteConn{perspective: pers}
|
||||
}
|
||||
|
||||
func (s *closedRemoteConn) handlePacket(*receivedPacket) {}
|
||||
func (s *closedRemoteConn) handlePacket(receivedPacket) {}
|
||||
func (s *closedRemoteConn) shutdown() {}
|
||||
func (s *closedRemoteConn) destroy(error) {}
|
||||
func (s *closedRemoteConn) getPerspective() protocol.Perspective { return s.perspective }
|
||||
|
|
17
vendor/github.com/quic-go/quic-go/config.go
generated
vendored
17
vendor/github.com/quic-go/quic-go/config.go
generated
vendored
|
@ -1,13 +1,13 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
)
|
||||
|
||||
// Clone clones a Config
|
||||
|
@ -24,11 +24,18 @@ func validateConfig(config *Config) error {
|
|||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
if config.MaxIncomingStreams > 1<<60 {
|
||||
return errors.New("invalid value for Config.MaxIncomingStreams")
|
||||
const maxStreams = 1 << 60
|
||||
if config.MaxIncomingStreams > maxStreams {
|
||||
config.MaxIncomingStreams = maxStreams
|
||||
}
|
||||
if config.MaxIncomingUniStreams > 1<<60 {
|
||||
return errors.New("invalid value for Config.MaxIncomingUniStreams")
|
||||
if config.MaxIncomingUniStreams > maxStreams {
|
||||
config.MaxIncomingUniStreams = maxStreams
|
||||
}
|
||||
if config.MaxStreamReceiveWindow > quicvarint.Max {
|
||||
config.MaxStreamReceiveWindow = quicvarint.Max
|
||||
}
|
||||
if config.MaxConnectionReceiveWindow > quicvarint.Max {
|
||||
config.MaxConnectionReceiveWindow = quicvarint.Max
|
||||
}
|
||||
// check that all QUIC versions are actually supported
|
||||
for _, v := range config.Versions {
|
||||
|
|
467
vendor/github.com/quic-go/quic-go/connection.go
generated
vendored
467
vendor/github.com/quic-go/quic-go/connection.go
generated
vendored
|
@ -61,11 +61,6 @@ type cryptoStreamHandler interface {
|
|||
ConnectionState() handshake.ConnectionState
|
||||
}
|
||||
|
||||
type packetInfo struct {
|
||||
addr net.IP
|
||||
ifIndex uint32
|
||||
}
|
||||
|
||||
type receivedPacket struct {
|
||||
buffer *packetBuffer
|
||||
|
||||
|
@ -75,7 +70,7 @@ type receivedPacket struct {
|
|||
|
||||
ecn protocol.ECN
|
||||
|
||||
info *packetInfo
|
||||
info packetInfo // only valid if the contained IP address is valid
|
||||
}
|
||||
|
||||
func (p *receivedPacket) Size() protocol.ByteCount { return protocol.ByteCount(len(p.data)) }
|
||||
|
@ -173,7 +168,7 @@ type connection struct {
|
|||
oneRTTStream cryptoStream // only set for the server
|
||||
cryptoStreamHandler cryptoStreamHandler
|
||||
|
||||
receivedPackets chan *receivedPacket
|
||||
receivedPackets chan receivedPacket
|
||||
sendingScheduled chan struct{}
|
||||
|
||||
closeOnce sync.Once
|
||||
|
@ -185,8 +180,8 @@ type connection struct {
|
|||
handshakeCtx context.Context
|
||||
handshakeCtxCancel context.CancelFunc
|
||||
|
||||
undecryptablePackets []*receivedPacket // undecryptable packets, waiting for a change in encryption level
|
||||
undecryptablePacketsToProcess []*receivedPacket
|
||||
undecryptablePackets []receivedPacket // undecryptable packets, waiting for a change in encryption level
|
||||
undecryptablePacketsToProcess []receivedPacket
|
||||
|
||||
clientHelloWritten <-chan *wire.TransportParameters
|
||||
earlyConnReadyChan chan struct{}
|
||||
|
@ -199,6 +194,7 @@ type connection struct {
|
|||
versionNegotiated bool
|
||||
receivedFirstPacket bool
|
||||
|
||||
// the minimum of the max_idle_timeout values advertised by both endpoints
|
||||
idleTimeout time.Duration
|
||||
creationTime time.Time
|
||||
// The idle timeout is set based on the max of the time we received the last packet...
|
||||
|
@ -297,6 +293,7 @@ var newConnection = func(
|
|||
s.tracer,
|
||||
s.logger,
|
||||
)
|
||||
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, getMaxPacketSize(s.conn.RemoteAddr()), s.sentPacketHandler.SetMaxDatagramSize)
|
||||
initialStream := newCryptoStream()
|
||||
handshakeStream := newCryptoStream()
|
||||
params := &wire.TransportParameters{
|
||||
|
@ -353,7 +350,7 @@ var newConnection = func(
|
|||
s.version,
|
||||
)
|
||||
s.cryptoStreamHandler = cs
|
||||
s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, initialStream, handshakeStream, s.sentPacketHandler, s.retransmissionQueue, s.RemoteAddr(), cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
|
||||
s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, initialStream, handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
|
||||
s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen)
|
||||
s.cryptoStreamManager = newCryptoStreamManager(cs, initialStream, handshakeStream, s.oneRTTStream)
|
||||
return s
|
||||
|
@ -418,6 +415,7 @@ var newClientConnection = func(
|
|||
s.tracer,
|
||||
s.logger,
|
||||
)
|
||||
s.mtuDiscoverer = newMTUDiscoverer(s.rttStats, getMaxPacketSize(s.conn.RemoteAddr()), s.sentPacketHandler.SetMaxDatagramSize)
|
||||
initialStream := newCryptoStream()
|
||||
handshakeStream := newCryptoStream()
|
||||
params := &wire.TransportParameters{
|
||||
|
@ -471,7 +469,7 @@ var newClientConnection = func(
|
|||
s.cryptoStreamHandler = cs
|
||||
s.cryptoStreamManager = newCryptoStreamManager(cs, initialStream, handshakeStream, newCryptoStream())
|
||||
s.unpacker = newPacketUnpacker(cs, s.srcConnIDLen)
|
||||
s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, initialStream, handshakeStream, s.sentPacketHandler, s.retransmissionQueue, s.RemoteAddr(), cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
|
||||
s.packer = newPacketPacker(srcConnID, s.connIDManager.Get, initialStream, handshakeStream, s.sentPacketHandler, s.retransmissionQueue, cs, s.framer, s.receivedPacketHandler, s.datagramQueue, s.perspective)
|
||||
if len(tlsConf.ServerName) > 0 {
|
||||
s.tokenStoreKey = tlsConf.ServerName
|
||||
} else {
|
||||
|
@ -512,7 +510,7 @@ func (s *connection) preSetup() {
|
|||
s.perspective,
|
||||
)
|
||||
s.framer = newFramer(s.streamsMap)
|
||||
s.receivedPackets = make(chan *receivedPacket, protocol.MaxConnUnprocessedPackets)
|
||||
s.receivedPackets = make(chan receivedPacket, protocol.MaxConnUnprocessedPackets)
|
||||
s.closeChan = make(chan closeError, 1)
|
||||
s.sendingScheduled = make(chan struct{}, 1)
|
||||
s.handshakeCtx, s.handshakeCtxCancel = context.WithCancel(context.Background())
|
||||
|
@ -665,7 +663,7 @@ runLoop:
|
|||
} else {
|
||||
idleTimeoutStartTime := s.idleTimeoutStartTime()
|
||||
if (!s.handshakeComplete && now.Sub(idleTimeoutStartTime) >= s.config.HandshakeIdleTimeout) ||
|
||||
(s.handshakeComplete && now.Sub(idleTimeoutStartTime) >= s.idleTimeout) {
|
||||
(s.handshakeComplete && now.After(s.nextIdleTimeoutTime())) {
|
||||
s.destroyImpl(qerr.ErrIdleTimeout)
|
||||
continue
|
||||
}
|
||||
|
@ -677,7 +675,7 @@ runLoop:
|
|||
sendQueueAvailable = s.sendQueue.Available()
|
||||
continue
|
||||
}
|
||||
if err := s.sendPackets(); err != nil {
|
||||
if err := s.triggerSending(); err != nil {
|
||||
s.closeLocal(err)
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
|
@ -689,12 +687,12 @@ runLoop:
|
|||
|
||||
s.cryptoStreamHandler.Close()
|
||||
<-handshaking
|
||||
s.sendQueue.Close() // close the send queue before sending the CONNECTION_CLOSE
|
||||
s.handleCloseError(&closeErr)
|
||||
if e := (&errCloseForRecreating{}); !errors.As(closeErr.err, &e) && s.tracer != nil {
|
||||
s.tracer.Close()
|
||||
}
|
||||
s.logger.Infof("Connection %s closed.", s.logID)
|
||||
s.sendQueue.Close()
|
||||
s.timer.Stop()
|
||||
return closeErr.err
|
||||
}
|
||||
|
@ -723,13 +721,20 @@ func (s *connection) ConnectionState() ConnectionState {
|
|||
return s.connState
|
||||
}
|
||||
|
||||
// Time when the connection should time out
|
||||
func (s *connection) nextIdleTimeoutTime() time.Time {
|
||||
idleTimeout := utils.Max(s.idleTimeout, s.rttStats.PTO(true)*3)
|
||||
return s.idleTimeoutStartTime().Add(idleTimeout)
|
||||
}
|
||||
|
||||
// Time when the next keep-alive packet should be sent.
|
||||
// It returns a zero time if no keep-alive should be sent.
|
||||
func (s *connection) nextKeepAliveTime() time.Time {
|
||||
if s.config.KeepAlivePeriod == 0 || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() {
|
||||
return time.Time{}
|
||||
}
|
||||
return s.lastPacketReceivedTime.Add(s.keepAliveInterval)
|
||||
keepAliveInterval := utils.Max(s.keepAliveInterval, s.rttStats.PTO(true)*3/2)
|
||||
return s.lastPacketReceivedTime.Add(keepAliveInterval)
|
||||
}
|
||||
|
||||
func (s *connection) maybeResetTimer() {
|
||||
|
@ -743,7 +748,7 @@ func (s *connection) maybeResetTimer() {
|
|||
if keepAliveTime := s.nextKeepAliveTime(); !keepAliveTime.IsZero() {
|
||||
deadline = keepAliveTime
|
||||
} else {
|
||||
deadline = s.idleTimeoutStartTime().Add(s.idleTimeout)
|
||||
deadline = s.nextIdleTimeoutTime()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -800,25 +805,16 @@ func (s *connection) handleHandshakeConfirmed() {
|
|||
s.sentPacketHandler.SetHandshakeConfirmed()
|
||||
s.cryptoStreamHandler.SetHandshakeConfirmed()
|
||||
|
||||
if !s.config.DisablePathMTUDiscovery {
|
||||
if !s.config.DisablePathMTUDiscovery && s.conn.capabilities().DF {
|
||||
maxPacketSize := s.peerParams.MaxUDPPayloadSize
|
||||
if maxPacketSize == 0 {
|
||||
maxPacketSize = protocol.MaxByteCount
|
||||
}
|
||||
maxPacketSize = utils.Min(maxPacketSize, protocol.MaxPacketBufferSize)
|
||||
s.mtuDiscoverer = newMTUDiscoverer(
|
||||
s.rttStats,
|
||||
getMaxPacketSize(s.conn.RemoteAddr()),
|
||||
maxPacketSize,
|
||||
func(size protocol.ByteCount) {
|
||||
s.sentPacketHandler.SetMaxDatagramSize(size)
|
||||
s.packer.SetMaxPacketSize(size)
|
||||
},
|
||||
)
|
||||
s.mtuDiscoverer.Start(utils.Min(maxPacketSize, protocol.MaxPacketBufferSize))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *connection) handlePacketImpl(rp *receivedPacket) bool {
|
||||
func (s *connection) handlePacketImpl(rp receivedPacket) bool {
|
||||
s.sentPacketHandler.ReceivedBytes(rp.Size())
|
||||
|
||||
if wire.IsVersionNegotiationPacket(rp.data) {
|
||||
|
@ -834,7 +830,7 @@ func (s *connection) handlePacketImpl(rp *receivedPacket) bool {
|
|||
for len(data) > 0 {
|
||||
var destConnID protocol.ConnectionID
|
||||
if counter > 0 {
|
||||
p = p.Clone()
|
||||
p = *(p.Clone())
|
||||
p.data = data
|
||||
|
||||
var err error
|
||||
|
@ -907,7 +903,7 @@ func (s *connection) handlePacketImpl(rp *receivedPacket) bool {
|
|||
return processed
|
||||
}
|
||||
|
||||
func (s *connection) handleShortHeaderPacket(p *receivedPacket, destConnID protocol.ConnectionID) bool {
|
||||
func (s *connection) handleShortHeaderPacket(p receivedPacket, destConnID protocol.ConnectionID) bool {
|
||||
var wasQueued bool
|
||||
|
||||
defer func() {
|
||||
|
@ -958,7 +954,7 @@ func (s *connection) handleShortHeaderPacket(p *receivedPacket, destConnID proto
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *connection) handleLongHeaderPacket(p *receivedPacket, hdr *wire.Header) bool /* was the packet successfully processed */ {
|
||||
func (s *connection) handleLongHeaderPacket(p receivedPacket, hdr *wire.Header) bool /* was the packet successfully processed */ {
|
||||
var wasQueued bool
|
||||
|
||||
defer func() {
|
||||
|
@ -1015,7 +1011,7 @@ func (s *connection) handleLongHeaderPacket(p *receivedPacket, hdr *wire.Header)
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *connection) handleUnpackError(err error, p *receivedPacket, pt logging.PacketType) (wasQueued bool) {
|
||||
func (s *connection) handleUnpackError(err error, p receivedPacket, pt logging.PacketType) (wasQueued bool) {
|
||||
switch err {
|
||||
case handshake.ErrKeysDropped:
|
||||
if s.tracer != nil {
|
||||
|
@ -1117,7 +1113,7 @@ func (s *connection) handleRetryPacket(hdr *wire.Header, data []byte) bool /* wa
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *connection) handleVersionNegotiationPacket(p *receivedPacket) {
|
||||
func (s *connection) handleVersionNegotiationPacket(p receivedPacket) {
|
||||
if s.perspective == protocol.PerspectiveServer || // servers never receive version negotiation packets
|
||||
s.receivedFirstPacket || s.versionNegotiated { // ignore delayed / duplicated version negotiation packets
|
||||
if s.tracer != nil {
|
||||
|
@ -1261,7 +1257,11 @@ func (s *connection) handleFrames(
|
|||
) (isAckEliciting bool, _ error) {
|
||||
// Only used for tracing.
|
||||
// If we're not tracing, this slice will always remain empty.
|
||||
var frames []wire.Frame
|
||||
var frames []logging.Frame
|
||||
if log != nil {
|
||||
frames = make([]logging.Frame, 0, 4)
|
||||
}
|
||||
var handleErr error
|
||||
for len(data) > 0 {
|
||||
l, frame, err := s.frameParser.ParseNext(data, encLevel, s.version)
|
||||
if err != nil {
|
||||
|
@ -1274,27 +1274,27 @@ func (s *connection) handleFrames(
|
|||
if ackhandler.IsFrameAckEliciting(frame) {
|
||||
isAckEliciting = true
|
||||
}
|
||||
// Only process frames now if we're not logging.
|
||||
// If we're logging, we need to make sure that the packet_received event is logged first.
|
||||
if log == nil {
|
||||
if err := s.handleFrame(frame, encLevel, destConnID); err != nil {
|
||||
if log != nil {
|
||||
frames = append(frames, logutils.ConvertFrame(frame))
|
||||
}
|
||||
// An error occurred handling a previous frame.
|
||||
// Don't handle the current frame.
|
||||
if handleErr != nil {
|
||||
continue
|
||||
}
|
||||
if err := s.handleFrame(frame, encLevel, destConnID); err != nil {
|
||||
if log == nil {
|
||||
return false, err
|
||||
}
|
||||
} else {
|
||||
frames = append(frames, frame)
|
||||
// If we're logging, we need to keep parsing (but not handling) all frames.
|
||||
handleErr = err
|
||||
}
|
||||
}
|
||||
|
||||
if log != nil {
|
||||
fs := make([]logging.Frame, len(frames))
|
||||
for i, frame := range frames {
|
||||
fs[i] = logutils.ConvertFrame(frame)
|
||||
}
|
||||
log(fs)
|
||||
for _, frame := range frames {
|
||||
if err := s.handleFrame(frame, encLevel, destConnID); err != nil {
|
||||
return false, err
|
||||
}
|
||||
log(frames)
|
||||
if handleErr != nil {
|
||||
return false, handleErr
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -1310,7 +1310,6 @@ func (s *connection) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel
|
|||
err = s.handleStreamFrame(frame)
|
||||
case *wire.AckFrame:
|
||||
err = s.handleAckFrame(frame, encLevel)
|
||||
wire.PutAckFrame(frame)
|
||||
case *wire.ConnectionCloseFrame:
|
||||
s.handleConnectionCloseFrame(frame)
|
||||
case *wire.ResetStreamFrame:
|
||||
|
@ -1349,7 +1348,7 @@ func (s *connection) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel
|
|||
}
|
||||
|
||||
// handlePacket is called by the server with a new packet
|
||||
func (s *connection) handlePacket(p *receivedPacket) {
|
||||
func (s *connection) handlePacket(p receivedPacket) {
|
||||
// Discard packets once the amount of queued packets is larger than
|
||||
// the channel size, protocol.MaxConnUnprocessedPackets
|
||||
select {
|
||||
|
@ -1723,7 +1722,6 @@ func (s *connection) applyTransportParameters() {
|
|||
s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout)
|
||||
s.keepAliveInterval = utils.Min(s.config.KeepAlivePeriod, utils.Min(s.idleTimeout/2, protocol.MaxKeepAliveInterval))
|
||||
s.streamsMap.UpdateLimits(params)
|
||||
s.packer.HandleTransportParameters(params)
|
||||
s.frameParser.SetAckDelayExponent(params.AckDelayExponent)
|
||||
s.connFlowController.UpdateSendWindow(params.InitialMaxData)
|
||||
s.rttStats.SetMaxAckDelay(params.MaxAckDelay)
|
||||
|
@ -1738,75 +1736,208 @@ func (s *connection) applyTransportParameters() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *connection) sendPackets() error {
|
||||
func (s *connection) triggerSending() error {
|
||||
s.pacingDeadline = time.Time{}
|
||||
now := time.Now()
|
||||
|
||||
var sentPacket bool // only used in for packets sent in send mode SendAny
|
||||
for {
|
||||
sendMode := s.sentPacketHandler.SendMode()
|
||||
if sendMode == ackhandler.SendAny && s.handshakeComplete && !s.sentPacketHandler.HasPacingBudget() {
|
||||
deadline := s.sentPacketHandler.TimeUntilSend()
|
||||
if deadline.IsZero() {
|
||||
deadline = deadlineSendImmediately
|
||||
}
|
||||
s.pacingDeadline = deadline
|
||||
// Allow sending of an ACK if we're pacing limit (if we haven't sent out a packet yet).
|
||||
// This makes sure that a peer that is mostly receiving data (and thus has an inaccurate cwnd estimate)
|
||||
// sends enough ACKs to allow its peer to utilize the bandwidth.
|
||||
if sentPacket {
|
||||
return nil
|
||||
}
|
||||
sendMode = ackhandler.SendAck
|
||||
sendMode := s.sentPacketHandler.SendMode(now)
|
||||
//nolint:exhaustive // No need to handle pacing limited here.
|
||||
switch sendMode {
|
||||
case ackhandler.SendAny:
|
||||
return s.sendPackets(now)
|
||||
case ackhandler.SendNone:
|
||||
return nil
|
||||
case ackhandler.SendPacingLimited:
|
||||
deadline := s.sentPacketHandler.TimeUntilSend()
|
||||
if deadline.IsZero() {
|
||||
deadline = deadlineSendImmediately
|
||||
}
|
||||
switch sendMode {
|
||||
case ackhandler.SendNone:
|
||||
s.pacingDeadline = deadline
|
||||
// Allow sending of an ACK if we're pacing limit.
|
||||
// This makes sure that a peer that is mostly receiving data (and thus has an inaccurate cwnd estimate)
|
||||
// sends enough ACKs to allow its peer to utilize the bandwidth.
|
||||
fallthrough
|
||||
case ackhandler.SendAck:
|
||||
// We can at most send a single ACK only packet.
|
||||
// There will only be a new ACK after receiving new packets.
|
||||
// SendAck is only returned when we're congestion limited, so we don't need to set the pacinggs timer.
|
||||
return s.maybeSendAckOnlyPacket(now)
|
||||
case ackhandler.SendPTOInitial:
|
||||
if err := s.sendProbePacket(protocol.EncryptionInitial, now); err != nil {
|
||||
return err
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
s.scheduleSending()
|
||||
return nil
|
||||
case ackhandler.SendAck:
|
||||
// If we already sent packets, and the send mode switches to SendAck,
|
||||
// as we've just become congestion limited.
|
||||
// There's no need to try to send an ACK at this moment.
|
||||
if sentPacket {
|
||||
}
|
||||
return s.triggerSending()
|
||||
case ackhandler.SendPTOHandshake:
|
||||
if err := s.sendProbePacket(protocol.EncryptionHandshake, now); err != nil {
|
||||
return err
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
s.scheduleSending()
|
||||
return nil
|
||||
}
|
||||
return s.triggerSending()
|
||||
case ackhandler.SendPTOAppData:
|
||||
if err := s.sendProbePacket(protocol.Encryption1RTT, now); err != nil {
|
||||
return err
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
s.scheduleSending()
|
||||
return nil
|
||||
}
|
||||
return s.triggerSending()
|
||||
default:
|
||||
return fmt.Errorf("BUG: invalid send mode %d", sendMode)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *connection) sendPackets(now time.Time) error {
|
||||
// Path MTU Discovery
|
||||
// Can't use GSO, since we need to send a single packet that's larger than our current maximum size.
|
||||
// Performance-wise, this doesn't matter, since we only send a very small (<10) number of
|
||||
// MTU probe packets per connection.
|
||||
if s.handshakeConfirmed && s.mtuDiscoverer != nil && s.mtuDiscoverer.ShouldSendProbe(now) {
|
||||
ping, size := s.mtuDiscoverer.GetPing()
|
||||
p, buf, err := s.packer.PackMTUProbePacket(ping, size, s.version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, buf.Len(), false)
|
||||
s.registerPackedShortHeaderPacket(p, now)
|
||||
s.sendQueue.Send(buf, buf.Len())
|
||||
// This is kind of a hack. We need to trigger sending again somehow.
|
||||
s.pacingDeadline = deadlineSendImmediately
|
||||
return nil
|
||||
}
|
||||
|
||||
if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked {
|
||||
s.framer.QueueControlFrame(&wire.DataBlockedFrame{MaximumData: offset})
|
||||
}
|
||||
s.windowUpdateQueue.QueueAll()
|
||||
|
||||
if !s.handshakeConfirmed {
|
||||
packet, err := s.packer.PackCoalescedPacket(false, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
if err != nil || packet == nil {
|
||||
return err
|
||||
}
|
||||
s.sentFirstPacket = true
|
||||
s.sendPackedCoalescedPacket(packet, now)
|
||||
sendMode := s.sentPacketHandler.SendMode(now)
|
||||
if sendMode == ackhandler.SendPacingLimited {
|
||||
s.resetPacingDeadline()
|
||||
} else if sendMode == ackhandler.SendAny {
|
||||
s.pacingDeadline = deadlineSendImmediately
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.conn.capabilities().GSO {
|
||||
return s.sendPacketsWithGSO(now)
|
||||
}
|
||||
return s.sendPacketsWithoutGSO(now)
|
||||
}
|
||||
|
||||
func (s *connection) sendPacketsWithoutGSO(now time.Time) error {
|
||||
for {
|
||||
buf := getPacketBuffer()
|
||||
if _, err := s.appendPacket(buf, s.mtuDiscoverer.CurrentSize(), now); err != nil {
|
||||
if err == errNothingToPack {
|
||||
buf.Release()
|
||||
return nil
|
||||
}
|
||||
// We can at most send a single ACK only packet.
|
||||
// There will only be a new ACK after receiving new packets.
|
||||
// SendAck is only returned when we're congestion limited, so we don't need to set the pacinggs timer.
|
||||
return s.maybeSendAckOnlyPacket()
|
||||
case ackhandler.SendPTOInitial:
|
||||
if err := s.sendProbePacket(protocol.EncryptionInitial); err != nil {
|
||||
return err
|
||||
}
|
||||
case ackhandler.SendPTOHandshake:
|
||||
if err := s.sendProbePacket(protocol.EncryptionHandshake); err != nil {
|
||||
return err
|
||||
}
|
||||
case ackhandler.SendPTOAppData:
|
||||
if err := s.sendProbePacket(protocol.Encryption1RTT); err != nil {
|
||||
return err
|
||||
}
|
||||
case ackhandler.SendAny:
|
||||
sent, err := s.sendPacket()
|
||||
if err != nil || !sent {
|
||||
return err
|
||||
}
|
||||
sentPacket = true
|
||||
default:
|
||||
return fmt.Errorf("BUG: invalid send mode %d", sendMode)
|
||||
return err
|
||||
}
|
||||
|
||||
s.sendQueue.Send(buf, buf.Len())
|
||||
|
||||
if s.sendQueue.WouldBlock() {
|
||||
return nil
|
||||
}
|
||||
sendMode := s.sentPacketHandler.SendMode(now)
|
||||
if sendMode == ackhandler.SendPacingLimited {
|
||||
s.resetPacingDeadline()
|
||||
return nil
|
||||
}
|
||||
if sendMode != ackhandler.SendAny {
|
||||
return nil
|
||||
}
|
||||
// Prioritize receiving of packets over sending out more packets.
|
||||
if len(s.receivedPackets) > 0 {
|
||||
s.pacingDeadline = deadlineSendImmediately
|
||||
return nil
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *connection) maybeSendAckOnlyPacket() error {
|
||||
func (s *connection) sendPacketsWithGSO(now time.Time) error {
|
||||
buf := getLargePacketBuffer()
|
||||
maxSize := s.mtuDiscoverer.CurrentSize()
|
||||
|
||||
for {
|
||||
var dontSendMore bool
|
||||
size, err := s.appendPacket(buf, maxSize, now)
|
||||
if err != nil {
|
||||
if err != errNothingToPack {
|
||||
return err
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
buf.Release()
|
||||
return nil
|
||||
}
|
||||
dontSendMore = true
|
||||
}
|
||||
|
||||
if !dontSendMore {
|
||||
sendMode := s.sentPacketHandler.SendMode(now)
|
||||
if sendMode == ackhandler.SendPacingLimited {
|
||||
s.resetPacingDeadline()
|
||||
}
|
||||
if sendMode != ackhandler.SendAny {
|
||||
dontSendMore = true
|
||||
}
|
||||
}
|
||||
|
||||
// Append another packet if
|
||||
// 1. The congestion controller and pacer allow sending more
|
||||
// 2. The last packet appended was a full-size packet
|
||||
// 3. We still have enough space for another full-size packet in the buffer
|
||||
if !dontSendMore && size == maxSize && buf.Len()+maxSize <= buf.Cap() {
|
||||
continue
|
||||
}
|
||||
|
||||
s.sendQueue.Send(buf, maxSize)
|
||||
|
||||
if dontSendMore {
|
||||
return nil
|
||||
}
|
||||
if s.sendQueue.WouldBlock() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prioritize receiving of packets over sending out more packets.
|
||||
if len(s.receivedPackets) > 0 {
|
||||
s.pacingDeadline = deadlineSendImmediately
|
||||
return nil
|
||||
}
|
||||
|
||||
buf = getLargePacketBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *connection) resetPacingDeadline() {
|
||||
deadline := s.sentPacketHandler.TimeUntilSend()
|
||||
if deadline.IsZero() {
|
||||
deadline = deadlineSendImmediately
|
||||
}
|
||||
s.pacingDeadline = deadline
|
||||
}
|
||||
|
||||
func (s *connection) maybeSendAckOnlyPacket(now time.Time) error {
|
||||
if !s.handshakeConfirmed {
|
||||
packet, err := s.packer.PackCoalescedPacket(true, s.version)
|
||||
packet, err := s.packer.PackCoalescedPacket(true, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1817,20 +1948,20 @@ func (s *connection) maybeSendAckOnlyPacket() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
p, buffer, err := s.packer.PackPacket(true, now, s.version)
|
||||
p, buf, err := s.packer.PackAckOnlyPacket(s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
if err != nil {
|
||||
if err == errNothingToPack {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, buffer.Len(), false)
|
||||
s.sendPackedShortHeaderPacket(buffer, p.Packet, now)
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, buf.Len(), false)
|
||||
s.registerPackedShortHeaderPacket(p, now)
|
||||
s.sendQueue.Send(buf, buf.Len())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel) error {
|
||||
func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel, now time.Time) error {
|
||||
// Queue probe packets until we actually send out a packet,
|
||||
// or until there are no more packets to queue.
|
||||
var packet *coalescedPacket
|
||||
|
@ -1839,7 +1970,7 @@ func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel) error {
|
|||
break
|
||||
}
|
||||
var err error
|
||||
packet, err = s.packer.MaybePackProbePacket(encLevel, s.version)
|
||||
packet, err = s.packer.MaybePackProbePacket(encLevel, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1848,19 +1979,9 @@ func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel) error {
|
|||
}
|
||||
}
|
||||
if packet == nil {
|
||||
//nolint:exhaustive // Cannot send probe packets for 0-RTT.
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
s.retransmissionQueue.AddInitial(&wire.PingFrame{})
|
||||
case protocol.EncryptionHandshake:
|
||||
s.retransmissionQueue.AddHandshake(&wire.PingFrame{})
|
||||
case protocol.Encryption1RTT:
|
||||
s.retransmissionQueue.AddAppData(&wire.PingFrame{})
|
||||
default:
|
||||
panic("unexpected encryption level")
|
||||
}
|
||||
s.retransmissionQueue.AddPing(encLevel)
|
||||
var err error
|
||||
packet, err = s.packer.MaybePackProbePacket(encLevel, s.version)
|
||||
packet, err = s.packer.MaybePackProbePacket(encLevel, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1868,55 +1989,35 @@ func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel) error {
|
|||
if packet == nil || (len(packet.longHdrPackets) == 0 && packet.shortHdrPacket == nil) {
|
||||
return fmt.Errorf("connection BUG: couldn't pack %s probe packet", encLevel)
|
||||
}
|
||||
s.sendPackedCoalescedPacket(packet, time.Now())
|
||||
s.sendPackedCoalescedPacket(packet, now)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *connection) sendPacket() (bool, error) {
|
||||
if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked {
|
||||
s.framer.QueueControlFrame(&wire.DataBlockedFrame{MaximumData: offset})
|
||||
}
|
||||
s.windowUpdateQueue.QueueAll()
|
||||
|
||||
now := time.Now()
|
||||
if !s.handshakeConfirmed {
|
||||
packet, err := s.packer.PackCoalescedPacket(false, s.version)
|
||||
if err != nil || packet == nil {
|
||||
return false, err
|
||||
}
|
||||
s.sentFirstPacket = true
|
||||
s.sendPackedCoalescedPacket(packet, now)
|
||||
return true, nil
|
||||
} else if !s.config.DisablePathMTUDiscovery && s.mtuDiscoverer.ShouldSendProbe(now) {
|
||||
ping, size := s.mtuDiscoverer.GetPing()
|
||||
p, buffer, err := s.packer.PackMTUProbePacket(ping, size, now, s.version)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, buffer.Len(), false)
|
||||
s.sendPackedShortHeaderPacket(buffer, p.Packet, now)
|
||||
return true, nil
|
||||
}
|
||||
p, buffer, err := s.packer.PackPacket(false, now, s.version)
|
||||
// appendPacket appends a new packet to the given packetBuffer.
|
||||
// If there was nothing to pack, the returned size is 0.
|
||||
func (s *connection) appendPacket(buf *packetBuffer, maxSize protocol.ByteCount, now time.Time) (protocol.ByteCount, error) {
|
||||
startLen := buf.Len()
|
||||
p, err := s.packer.AppendPacket(buf, maxSize, s.version)
|
||||
if err != nil {
|
||||
if err == errNothingToPack {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
return 0, err
|
||||
}
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, buffer.Len(), false)
|
||||
s.sendPackedShortHeaderPacket(buffer, p.Packet, now)
|
||||
return true, nil
|
||||
size := buf.Len() - startLen
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, size, false)
|
||||
s.registerPackedShortHeaderPacket(p, now)
|
||||
return size, nil
|
||||
}
|
||||
|
||||
func (s *connection) sendPackedShortHeaderPacket(buffer *packetBuffer, p *ackhandler.Packet, now time.Time) {
|
||||
if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && ackhandler.HasAckElicitingFrames(p.Frames) {
|
||||
func (s *connection) registerPackedShortHeaderPacket(p shortHeaderPacket, now time.Time) {
|
||||
if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && (len(p.StreamFrames) > 0 || ackhandler.HasAckElicitingFrames(p.Frames)) {
|
||||
s.firstAckElicitingPacketAfterIdleSentTime = now
|
||||
}
|
||||
|
||||
s.sentPacketHandler.SentPacket(p)
|
||||
largestAcked := protocol.InvalidPacketNumber
|
||||
if p.Ack != nil {
|
||||
largestAcked = p.Ack.LargestAcked()
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(now, p.PacketNumber, largestAcked, p.StreamFrames, p.Frames, protocol.Encryption1RTT, p.Length, p.IsPathMTUProbePacket)
|
||||
s.connIDManager.SentPacket()
|
||||
s.sendQueue.Send(buffer)
|
||||
}
|
||||
|
||||
func (s *connection) sendPackedCoalescedPacket(packet *coalescedPacket, now time.Time) {
|
||||
|
@ -1925,16 +2026,24 @@ func (s *connection) sendPackedCoalescedPacket(packet *coalescedPacket, now time
|
|||
if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && p.IsAckEliciting() {
|
||||
s.firstAckElicitingPacketAfterIdleSentTime = now
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(p.ToAckHandlerPacket(now, s.retransmissionQueue))
|
||||
largestAcked := protocol.InvalidPacketNumber
|
||||
if p.ack != nil {
|
||||
largestAcked = p.ack.LargestAcked()
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(now, p.header.PacketNumber, largestAcked, p.streamFrames, p.frames, p.EncryptionLevel(), p.length, false)
|
||||
}
|
||||
if p := packet.shortHdrPacket; p != nil {
|
||||
if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && p.IsAckEliciting() {
|
||||
s.firstAckElicitingPacketAfterIdleSentTime = now
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(p.Packet)
|
||||
largestAcked := protocol.InvalidPacketNumber
|
||||
if p.Ack != nil {
|
||||
largestAcked = p.Ack.LargestAcked()
|
||||
}
|
||||
s.sentPacketHandler.SentPacket(now, p.PacketNumber, largestAcked, p.StreamFrames, p.Frames, protocol.Encryption1RTT, p.Length, p.IsPathMTUProbePacket)
|
||||
}
|
||||
s.connIDManager.SentPacket()
|
||||
s.sendQueue.Send(packet.buffer)
|
||||
s.sendQueue.Send(packet.buffer, packet.buffer.Len())
|
||||
}
|
||||
|
||||
func (s *connection) sendConnectionClose(e error) ([]byte, error) {
|
||||
|
@ -1943,20 +2052,20 @@ func (s *connection) sendConnectionClose(e error) ([]byte, error) {
|
|||
var transportErr *qerr.TransportError
|
||||
var applicationErr *qerr.ApplicationError
|
||||
if errors.As(e, &transportErr) {
|
||||
packet, err = s.packer.PackConnectionClose(transportErr, s.version)
|
||||
packet, err = s.packer.PackConnectionClose(transportErr, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
} else if errors.As(e, &applicationErr) {
|
||||
packet, err = s.packer.PackApplicationClose(applicationErr, s.version)
|
||||
packet, err = s.packer.PackApplicationClose(applicationErr, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
} else {
|
||||
packet, err = s.packer.PackConnectionClose(&qerr.TransportError{
|
||||
ErrorCode: qerr.InternalError,
|
||||
ErrorMessage: fmt.Sprintf("connection BUG: unspecified error type (msg: %s)", e.Error()),
|
||||
}, s.version)
|
||||
}, s.mtuDiscoverer.CurrentSize(), s.version)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.logCoalescedPacket(packet)
|
||||
return packet.buffer.Data, s.conn.Write(packet.buffer.Data)
|
||||
return packet.buffer.Data, s.conn.Write(packet.buffer.Data, packet.buffer.Len())
|
||||
}
|
||||
|
||||
func (s *connection) logLongHeaderPacket(p *longHeaderPacket) {
|
||||
|
@ -1988,7 +2097,8 @@ func (s *connection) logLongHeaderPacket(p *longHeaderPacket) {
|
|||
func (s *connection) logShortHeaderPacket(
|
||||
destConnID protocol.ConnectionID,
|
||||
ackFrame *wire.AckFrame,
|
||||
frames []*ackhandler.Frame,
|
||||
frames []ackhandler.Frame,
|
||||
streamFrames []ackhandler.StreamFrame,
|
||||
pn protocol.PacketNumber,
|
||||
pnLen protocol.PacketNumberLen,
|
||||
kp protocol.KeyPhaseBit,
|
||||
|
@ -2004,17 +2114,23 @@ func (s *connection) logShortHeaderPacket(
|
|||
if ackFrame != nil {
|
||||
wire.LogFrame(s.logger, ackFrame, true)
|
||||
}
|
||||
for _, frame := range frames {
|
||||
wire.LogFrame(s.logger, frame.Frame, true)
|
||||
for _, f := range frames {
|
||||
wire.LogFrame(s.logger, f.Frame, true)
|
||||
}
|
||||
for _, f := range streamFrames {
|
||||
wire.LogFrame(s.logger, f.Frame, true)
|
||||
}
|
||||
}
|
||||
|
||||
// tracing
|
||||
if s.tracer != nil {
|
||||
fs := make([]logging.Frame, 0, len(frames))
|
||||
fs := make([]logging.Frame, 0, len(frames)+len(streamFrames))
|
||||
for _, f := range frames {
|
||||
fs = append(fs, logutils.ConvertFrame(f.Frame))
|
||||
}
|
||||
for _, f := range streamFrames {
|
||||
fs = append(fs, logutils.ConvertFrame(f.Frame))
|
||||
}
|
||||
var ack *logging.AckFrame
|
||||
if ackFrame != nil {
|
||||
ack = logutils.ConvertAckFrame(ackFrame)
|
||||
|
@ -2042,6 +2158,7 @@ func (s *connection) logCoalescedPacket(packet *coalescedPacket) {
|
|||
packet.shortHdrPacket.DestConnID,
|
||||
packet.shortHdrPacket.Ack,
|
||||
packet.shortHdrPacket.Frames,
|
||||
packet.shortHdrPacket.StreamFrames,
|
||||
packet.shortHdrPacket.PacketNumber,
|
||||
packet.shortHdrPacket.PacketNumberLen,
|
||||
packet.shortHdrPacket.KeyPhase,
|
||||
|
@ -2060,7 +2177,7 @@ func (s *connection) logCoalescedPacket(packet *coalescedPacket) {
|
|||
s.logLongHeaderPacket(p)
|
||||
}
|
||||
if p := packet.shortHdrPacket; p != nil {
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, p.Length, true)
|
||||
s.logShortHeaderPacket(p.DestConnID, p.Ack, p.Frames, p.StreamFrames, p.PacketNumber, p.PacketNumberLen, p.KeyPhase, p.Length, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2121,7 +2238,7 @@ func (s *connection) scheduleSending() {
|
|||
|
||||
// tryQueueingUndecryptablePacket queues a packet for which we're missing the decryption keys.
|
||||
// The logging.PacketType is only used for logging purposes.
|
||||
func (s *connection) tryQueueingUndecryptablePacket(p *receivedPacket, pt logging.PacketType) {
|
||||
func (s *connection) tryQueueingUndecryptablePacket(p receivedPacket, pt logging.PacketType) {
|
||||
if s.handshakeComplete {
|
||||
panic("shouldn't queue undecryptable packets after handshake completion")
|
||||
}
|
||||
|
|
49
vendor/github.com/quic-go/quic-go/framer.go
generated
vendored
49
vendor/github.com/quic-go/quic-go/framer.go
generated
vendored
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/quic-go/quic-go/internal/ackhandler"
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/utils/ringbuffer"
|
||||
"github.com/quic-go/quic-go/internal/wire"
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
)
|
||||
|
@ -14,10 +15,10 @@ type framer interface {
|
|||
HasData() bool
|
||||
|
||||
QueueControlFrame(wire.Frame)
|
||||
AppendControlFrames([]*ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount)
|
||||
AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)
|
||||
|
||||
AddActiveStream(protocol.StreamID)
|
||||
AppendStreamFrames([]*ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount)
|
||||
AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)
|
||||
|
||||
Handle0RTTRejection() error
|
||||
}
|
||||
|
@ -28,7 +29,7 @@ type framerI struct {
|
|||
streamGetter streamGetter
|
||||
|
||||
activeStreams map[protocol.StreamID]struct{}
|
||||
streamQueue []protocol.StreamID
|
||||
streamQueue ringbuffer.RingBuffer[protocol.StreamID]
|
||||
|
||||
controlFrameMutex sync.Mutex
|
||||
controlFrames []wire.Frame
|
||||
|
@ -45,7 +46,7 @@ func newFramer(streamGetter streamGetter) framer {
|
|||
|
||||
func (f *framerI) HasData() bool {
|
||||
f.mutex.Lock()
|
||||
hasData := len(f.streamQueue) > 0
|
||||
hasData := !f.streamQueue.Empty()
|
||||
f.mutex.Unlock()
|
||||
if hasData {
|
||||
return true
|
||||
|
@ -62,7 +63,7 @@ func (f *framerI) QueueControlFrame(frame wire.Frame) {
|
|||
f.controlFrameMutex.Unlock()
|
||||
}
|
||||
|
||||
func (f *framerI) AppendControlFrames(frames []*ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount) {
|
||||
func (f *framerI) AppendControlFrames(frames []ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount) {
|
||||
var length protocol.ByteCount
|
||||
f.controlFrameMutex.Lock()
|
||||
for len(f.controlFrames) > 0 {
|
||||
|
@ -71,9 +72,7 @@ func (f *framerI) AppendControlFrames(frames []*ackhandler.Frame, maxLen protoco
|
|||
if length+frameLen > maxLen {
|
||||
break
|
||||
}
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = frame
|
||||
frames = append(frames, af)
|
||||
frames = append(frames, ackhandler.Frame{Frame: frame})
|
||||
length += frameLen
|
||||
f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
|
||||
}
|
||||
|
@ -84,24 +83,23 @@ func (f *framerI) AppendControlFrames(frames []*ackhandler.Frame, maxLen protoco
|
|||
func (f *framerI) AddActiveStream(id protocol.StreamID) {
|
||||
f.mutex.Lock()
|
||||
if _, ok := f.activeStreams[id]; !ok {
|
||||
f.streamQueue = append(f.streamQueue, id)
|
||||
f.streamQueue.PushBack(id)
|
||||
f.activeStreams[id] = struct{}{}
|
||||
}
|
||||
f.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (f *framerI) AppendStreamFrames(frames []*ackhandler.Frame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount) {
|
||||
func (f *framerI) AppendStreamFrames(frames []ackhandler.StreamFrame, maxLen protocol.ByteCount, v protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount) {
|
||||
startLen := len(frames)
|
||||
var length protocol.ByteCount
|
||||
var lastFrame *ackhandler.Frame
|
||||
f.mutex.Lock()
|
||||
// pop STREAM frames, until less than MinStreamFrameSize bytes are left in the packet
|
||||
numActiveStreams := len(f.streamQueue)
|
||||
numActiveStreams := f.streamQueue.Len()
|
||||
for i := 0; i < numActiveStreams; i++ {
|
||||
if protocol.MinStreamFrameSize+length > maxLen {
|
||||
break
|
||||
}
|
||||
id := f.streamQueue[0]
|
||||
f.streamQueue = f.streamQueue[1:]
|
||||
id := f.streamQueue.PopFront()
|
||||
// This should never return an error. Better check it anyway.
|
||||
// The stream will only be in the streamQueue, if it enqueued itself there.
|
||||
str, err := f.streamGetter.GetOrOpenSendStream(id)
|
||||
|
@ -115,28 +113,27 @@ func (f *framerI) AppendStreamFrames(frames []*ackhandler.Frame, maxLen protocol
|
|||
// Therefore, we can pretend to have more bytes available when popping
|
||||
// the STREAM frame (which will always have the DataLen set).
|
||||
remainingLen += quicvarint.Len(uint64(remainingLen))
|
||||
frame, hasMoreData := str.popStreamFrame(remainingLen, v)
|
||||
frame, ok, hasMoreData := str.popStreamFrame(remainingLen, v)
|
||||
if hasMoreData { // put the stream back in the queue (at the end)
|
||||
f.streamQueue = append(f.streamQueue, id)
|
||||
} else { // no more data to send. Stream is not active any more
|
||||
f.streamQueue.PushBack(id)
|
||||
} else { // no more data to send. Stream is not active
|
||||
delete(f.activeStreams, id)
|
||||
}
|
||||
// The frame can be nil
|
||||
// The frame can be "nil"
|
||||
// * if the receiveStream was canceled after it said it had data
|
||||
// * the remaining size doesn't allow us to add another STREAM frame
|
||||
if frame == nil {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
frames = append(frames, frame)
|
||||
length += frame.Length(v)
|
||||
lastFrame = frame
|
||||
length += frame.Frame.Length(v)
|
||||
}
|
||||
f.mutex.Unlock()
|
||||
if lastFrame != nil {
|
||||
lastFrameLen := lastFrame.Length(v)
|
||||
if len(frames) > startLen {
|
||||
l := frames[len(frames)-1].Frame.Length(v)
|
||||
// account for the smaller size of the last STREAM frame
|
||||
lastFrame.Frame.(*wire.StreamFrame).DataLenPresent = false
|
||||
length += lastFrame.Length(v) - lastFrameLen
|
||||
frames[len(frames)-1].Frame.DataLenPresent = false
|
||||
length += frames[len(frames)-1].Frame.Length(v) - l
|
||||
}
|
||||
return frames, length
|
||||
}
|
||||
|
@ -146,7 +143,7 @@ func (f *framerI) Handle0RTTRejection() error {
|
|||
defer f.mutex.Unlock()
|
||||
|
||||
f.controlFrameMutex.Lock()
|
||||
f.streamQueue = f.streamQueue[:0]
|
||||
f.streamQueue.Clear()
|
||||
for id := range f.activeStreams {
|
||||
delete(f.activeStreams, id)
|
||||
}
|
||||
|
|
40
vendor/github.com/quic-go/quic-go/http3/server.go
generated
vendored
40
vendor/github.com/quic-go/quic-go/http3/server.go
generated
vendored
|
@ -262,13 +262,26 @@ func (s *Server) ServeQUICConn(conn quic.Connection) error {
|
|||
// Make sure you use http3.ConfigureTLSConfig to configure a tls.Config
|
||||
// and use it to construct a http3-friendly QUIC listener.
|
||||
// Closing the server does close the listener.
|
||||
// ServeListener always returns a non-nil error. After Shutdown or Close, the returned error is http.ErrServerClosed.
|
||||
func (s *Server) ServeListener(ln QUICEarlyListener) error {
|
||||
if err := s.addListener(&ln); err != nil {
|
||||
return err
|
||||
}
|
||||
err := s.serveListener(ln)
|
||||
s.removeListener(&ln)
|
||||
return err
|
||||
defer s.removeListener(&ln)
|
||||
for {
|
||||
conn, err := ln.Accept(context.Background())
|
||||
if err == quic.ErrServerClosed {
|
||||
return http.ErrServerClosed
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if err := s.handleConn(conn); err != nil {
|
||||
s.logger.Debugf(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
var errServerWithoutTLSConfig = errors.New("use of http3.Server without TLSConfig")
|
||||
|
@ -310,26 +323,7 @@ func (s *Server) serveConn(tlsConf *tls.Config, conn net.PacketConn) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.addListener(&ln); err != nil {
|
||||
return err
|
||||
}
|
||||
err = s.serveListener(ln)
|
||||
s.removeListener(&ln)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Server) serveListener(ln QUICEarlyListener) error {
|
||||
for {
|
||||
conn, err := ln.Accept(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if err := s.handleConn(conn); err != nil {
|
||||
s.logger.Debugf(err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
return s.ServeListener(ln)
|
||||
}
|
||||
|
||||
func extractPort(addr string) (int, error) {
|
||||
|
|
23
vendor/github.com/quic-go/quic-go/interface.go
generated
vendored
23
vendor/github.com/quic-go/quic-go/interface.go
generated
vendored
|
@ -276,17 +276,21 @@ type Config struct {
|
|||
// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
|
||||
// will increase the window up to MaxStreamReceiveWindow.
|
||||
// If this value is zero, it will default to 512 KB.
|
||||
// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
|
||||
InitialStreamReceiveWindow uint64
|
||||
// MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
|
||||
// If this value is zero, it will default to 6 MB.
|
||||
// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
|
||||
MaxStreamReceiveWindow uint64
|
||||
// InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
|
||||
// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
|
||||
// will increase the window up to MaxConnectionReceiveWindow.
|
||||
// If this value is zero, it will default to 512 KB.
|
||||
// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
|
||||
InitialConnectionReceiveWindow uint64
|
||||
// MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
|
||||
// If this value is zero, it will default to 15 MB.
|
||||
// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
|
||||
MaxConnectionReceiveWindow uint64
|
||||
// AllowConnectionWindowIncrease is called every time the connection flow controller attempts
|
||||
// to increase the connection flow control window.
|
||||
|
@ -296,22 +300,23 @@ type Config struct {
|
|||
// in this callback.
|
||||
AllowConnectionWindowIncrease func(conn Connection, delta uint64) bool
|
||||
// MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
|
||||
// Values above 2^60 are invalid.
|
||||
// If not set, it will default to 100.
|
||||
// If set to a negative value, it doesn't allow any bidirectional streams.
|
||||
// Values larger than 2^60 will be clipped to that value.
|
||||
MaxIncomingStreams int64
|
||||
// MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
|
||||
// Values above 2^60 are invalid.
|
||||
// If not set, it will default to 100.
|
||||
// If set to a negative value, it doesn't allow any unidirectional streams.
|
||||
// Values larger than 2^60 will be clipped to that value.
|
||||
MaxIncomingUniStreams int64
|
||||
// KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive.
|
||||
// If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most
|
||||
// every half of MaxIdleTimeout, whichever is smaller).
|
||||
KeepAlivePeriod time.Duration
|
||||
// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
|
||||
// Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
|
||||
// Note that if Path MTU discovery is causing issues on your system, please open a new issue
|
||||
// This allows the sending of QUIC packets that fully utilize the available MTU of the path.
|
||||
// Path MTU discovery is only available on systems that allow setting of the Don't Fragment (DF) bit.
|
||||
// If unavailable or disabled, packets will be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
|
||||
DisablePathMTUDiscovery bool
|
||||
// DisableVersionNegotiationPackets disables the sending of Version Negotiation packets.
|
||||
// This can be useful if version information is exchanged out-of-band.
|
||||
|
@ -331,7 +336,13 @@ type ClientHelloInfo struct {
|
|||
|
||||
// ConnectionState records basic details about a QUIC connection
|
||||
type ConnectionState struct {
|
||||
TLS handshake.ConnectionState
|
||||
// TLS contains information about the TLS connection state, incl. the tls.ConnectionState.
|
||||
TLS handshake.ConnectionState
|
||||
// SupportsDatagrams says if support for QUIC datagrams (RFC 9221) was negotiated.
|
||||
// This requires both nodes to support and enable the datagram extensions (via Config.EnableDatagrams).
|
||||
// If datagram support was negotiated, datagrams can be sent and received using the
|
||||
// SendMessage and ReceiveMessage methods on the Connection.
|
||||
SupportsDatagrams bool
|
||||
Version VersionNumber
|
||||
// Version is the QUIC version of the QUIC connection.
|
||||
Version VersionNumber
|
||||
}
|
||||
|
|
2
vendor/github.com/quic-go/quic-go/internal/ackhandler/ack_eliciting.go
generated
vendored
2
vendor/github.com/quic-go/quic-go/internal/ackhandler/ack_eliciting.go
generated
vendored
|
@ -10,7 +10,7 @@ func IsFrameAckEliciting(f wire.Frame) bool {
|
|||
}
|
||||
|
||||
// HasAckElicitingFrames returns true if at least one frame is ack-eliciting.
|
||||
func HasAckElicitingFrames(fs []*Frame) bool {
|
||||
func HasAckElicitingFrames(fs []Frame) bool {
|
||||
for _, f := range fs {
|
||||
if IsFrameAckEliciting(f.Frame) {
|
||||
return true
|
||||
|
|
30
vendor/github.com/quic-go/quic-go/internal/ackhandler/frame.go
generated
vendored
30
vendor/github.com/quic-go/quic-go/internal/ackhandler/frame.go
generated
vendored
|
@ -1,29 +1,21 @@
|
|||
package ackhandler
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
// FrameHandler handles the acknowledgement and the loss of a frame.
|
||||
type FrameHandler interface {
|
||||
OnAcked(wire.Frame)
|
||||
OnLost(wire.Frame)
|
||||
}
|
||||
|
||||
type Frame struct {
|
||||
wire.Frame // nil if the frame has already been acknowledged in another packet
|
||||
OnLost func(wire.Frame)
|
||||
OnAcked func(wire.Frame)
|
||||
Frame wire.Frame // nil if the frame has already been acknowledged in another packet
|
||||
Handler FrameHandler
|
||||
}
|
||||
|
||||
var framePool = sync.Pool{New: func() any { return &Frame{} }}
|
||||
|
||||
func GetFrame() *Frame {
|
||||
f := framePool.Get().(*Frame)
|
||||
f.OnLost = nil
|
||||
f.OnAcked = nil
|
||||
return f
|
||||
}
|
||||
|
||||
func putFrame(f *Frame) {
|
||||
f.Frame = nil
|
||||
f.OnLost = nil
|
||||
f.OnAcked = nil
|
||||
framePool.Put(f)
|
||||
type StreamFrame struct {
|
||||
Frame *wire.StreamFrame
|
||||
Handler FrameHandler
|
||||
}
|
||||
|
|
10
vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go
generated
vendored
10
vendor/github.com/quic-go/quic-go/internal/ackhandler/interfaces.go
generated
vendored
|
@ -10,20 +10,20 @@ import (
|
|||
// SentPacketHandler handles ACKs received for outgoing packets
|
||||
type SentPacketHandler interface {
|
||||
// SentPacket may modify the packet
|
||||
SentPacket(packet *Packet)
|
||||
ReceivedAck(ackFrame *wire.AckFrame, encLevel protocol.EncryptionLevel, recvTime time.Time) (bool /* 1-RTT packet acked */, error)
|
||||
SentPacket(t time.Time, pn, largestAcked protocol.PacketNumber, streamFrames []StreamFrame, frames []Frame, encLevel protocol.EncryptionLevel, size protocol.ByteCount, isPathMTUProbePacket bool)
|
||||
// ReceivedAck processes an ACK frame.
|
||||
// It does not store a copy of the frame.
|
||||
ReceivedAck(f *wire.AckFrame, encLevel protocol.EncryptionLevel, recvTime time.Time) (bool /* 1-RTT packet acked */, error)
|
||||
ReceivedBytes(protocol.ByteCount)
|
||||
DropPackets(protocol.EncryptionLevel)
|
||||
ResetForRetry() error
|
||||
SetHandshakeConfirmed()
|
||||
|
||||
// The SendMode determines if and what kind of packets can be sent.
|
||||
SendMode() SendMode
|
||||
SendMode(now time.Time) SendMode
|
||||
// TimeUntilSend is the time when the next packet should be sent.
|
||||
// It is used for pacing packets.
|
||||
TimeUntilSend() time.Time
|
||||
// HasPacingBudget says if the pacer allows sending of a (full size) packet at this moment.
|
||||
HasPacingBudget() bool
|
||||
SetMaxDatagramSize(count protocol.ByteCount)
|
||||
|
||||
// only to be called once the handshake is complete
|
||||
|
|
20
vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go
generated
vendored
20
vendor/github.com/quic-go/quic-go/internal/ackhandler/packet.go
generated
vendored
|
@ -8,10 +8,11 @@ import (
|
|||
)
|
||||
|
||||
// A Packet is a packet
|
||||
type Packet struct {
|
||||
type packet struct {
|
||||
SendTime time.Time
|
||||
PacketNumber protocol.PacketNumber
|
||||
Frames []*Frame
|
||||
StreamFrames []StreamFrame
|
||||
Frames []Frame
|
||||
LargestAcked protocol.PacketNumber // InvalidPacketNumber if the packet doesn't contain an ACK
|
||||
Length protocol.ByteCount
|
||||
EncryptionLevel protocol.EncryptionLevel
|
||||
|
@ -23,15 +24,16 @@ type Packet struct {
|
|||
skippedPacket bool
|
||||
}
|
||||
|
||||
func (p *Packet) outstanding() bool {
|
||||
func (p *packet) outstanding() bool {
|
||||
return !p.declaredLost && !p.skippedPacket && !p.IsPathMTUProbePacket
|
||||
}
|
||||
|
||||
var packetPool = sync.Pool{New: func() any { return &Packet{} }}
|
||||
var packetPool = sync.Pool{New: func() any { return &packet{} }}
|
||||
|
||||
func GetPacket() *Packet {
|
||||
p := packetPool.Get().(*Packet)
|
||||
func getPacket() *packet {
|
||||
p := packetPool.Get().(*packet)
|
||||
p.PacketNumber = 0
|
||||
p.StreamFrames = nil
|
||||
p.Frames = nil
|
||||
p.LargestAcked = 0
|
||||
p.Length = 0
|
||||
|
@ -46,10 +48,8 @@ func GetPacket() *Packet {
|
|||
|
||||
// We currently only return Packets back into the pool when they're acknowledged (not when they're lost).
|
||||
// This simplifies the code, and gives the vast majority of the performance benefit we can gain from using the pool.
|
||||
func putPacket(p *Packet) {
|
||||
for _, f := range p.Frames {
|
||||
putFrame(f)
|
||||
}
|
||||
func putPacket(p *packet) {
|
||||
p.Frames = nil
|
||||
p.StreamFrames = nil
|
||||
packetPool.Put(p)
|
||||
}
|
||||
|
|
24
vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go
generated
vendored
24
vendor/github.com/quic-go/quic-go/internal/ackhandler/packet_number_generator.go
generated
vendored
|
@ -7,7 +7,10 @@ import (
|
|||
|
||||
type packetNumberGenerator interface {
|
||||
Peek() protocol.PacketNumber
|
||||
Pop() protocol.PacketNumber
|
||||
// Pop pops the packet number.
|
||||
// It reports if the packet number (before the one just popped) was skipped.
|
||||
// It never skips more than one packet number in a row.
|
||||
Pop() (skipped bool, _ protocol.PacketNumber)
|
||||
}
|
||||
|
||||
type sequentialPacketNumberGenerator struct {
|
||||
|
@ -24,10 +27,10 @@ func (p *sequentialPacketNumberGenerator) Peek() protocol.PacketNumber {
|
|||
return p.next
|
||||
}
|
||||
|
||||
func (p *sequentialPacketNumberGenerator) Pop() protocol.PacketNumber {
|
||||
func (p *sequentialPacketNumberGenerator) Pop() (bool, protocol.PacketNumber) {
|
||||
next := p.next
|
||||
p.next++
|
||||
return next
|
||||
return false, next
|
||||
}
|
||||
|
||||
// The skippingPacketNumberGenerator generates the packet number for the next packet
|
||||
|
@ -56,21 +59,26 @@ func newSkippingPacketNumberGenerator(initial, initialPeriod, maxPeriod protocol
|
|||
}
|
||||
|
||||
func (p *skippingPacketNumberGenerator) Peek() protocol.PacketNumber {
|
||||
if p.next == p.nextToSkip {
|
||||
return p.next + 1
|
||||
}
|
||||
return p.next
|
||||
}
|
||||
|
||||
func (p *skippingPacketNumberGenerator) Pop() protocol.PacketNumber {
|
||||
func (p *skippingPacketNumberGenerator) Pop() (bool, protocol.PacketNumber) {
|
||||
next := p.next
|
||||
p.next++ // generate a new packet number for the next packet
|
||||
if p.next == p.nextToSkip {
|
||||
p.next++
|
||||
next++
|
||||
p.next += 2
|
||||
p.generateNewSkip()
|
||||
return true, next
|
||||
}
|
||||
return next
|
||||
p.next++ // generate a new packet number for the next packet
|
||||
return false, next
|
||||
}
|
||||
|
||||
func (p *skippingPacketNumberGenerator) generateNewSkip() {
|
||||
// make sure that there are never two consecutive packet numbers that are skipped
|
||||
p.nextToSkip = p.next + 2 + protocol.PacketNumber(p.rng.Int31n(int32(2*p.period)))
|
||||
p.nextToSkip = p.next + 3 + protocol.PacketNumber(p.rng.Int31n(int32(2*p.period)))
|
||||
p.period = utils.Min(2*p.period, p.maxPeriod)
|
||||
}
|
||||
|
|
10
vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go
generated
vendored
10
vendor/github.com/quic-go/quic-go/internal/ackhandler/received_packet_tracker.go
generated
vendored
|
@ -169,16 +169,18 @@ func (h *receivedPacketTracker) GetAckFrame(onlyIfQueued bool) *wire.AckFrame {
|
|||
}
|
||||
}
|
||||
|
||||
ack := wire.GetAckFrame()
|
||||
// This function always returns the same ACK frame struct, filled with the most recent values.
|
||||
ack := h.lastAck
|
||||
if ack == nil {
|
||||
ack = &wire.AckFrame{}
|
||||
}
|
||||
ack.Reset()
|
||||
ack.DelayTime = utils.Max(0, now.Sub(h.largestObservedReceivedTime))
|
||||
ack.ECT0 = h.ect0
|
||||
ack.ECT1 = h.ect1
|
||||
ack.ECNCE = h.ecnce
|
||||
ack.AckRanges = h.packetHistory.AppendAckRanges(ack.AckRanges)
|
||||
|
||||
if h.lastAck != nil {
|
||||
wire.PutAckFrame(h.lastAck)
|
||||
}
|
||||
h.lastAck = ack
|
||||
h.ackAlarm = time.Time{}
|
||||
h.ackQueued = false
|
||||
|
|
6
vendor/github.com/quic-go/quic-go/internal/ackhandler/send_mode.go
generated
vendored
6
vendor/github.com/quic-go/quic-go/internal/ackhandler/send_mode.go
generated
vendored
|
@ -16,6 +16,10 @@ const (
|
|||
SendPTOHandshake
|
||||
// SendPTOAppData means that an Application data probe packet should be sent
|
||||
SendPTOAppData
|
||||
// SendPacingLimited means that the pacer doesn't allow sending of a packet right now,
|
||||
// but will do in a little while.
|
||||
// The timestamp when sending is allowed again can be obtained via the SentPacketHandler.TimeUntilSend.
|
||||
SendPacingLimited
|
||||
// SendAny means that any packet should be sent
|
||||
SendAny
|
||||
)
|
||||
|
@ -34,6 +38,8 @@ func (s SendMode) String() string {
|
|||
return "pto (Application Data)"
|
||||
case SendAny:
|
||||
return "any"
|
||||
case SendPacingLimited:
|
||||
return "pacing limited"
|
||||
default:
|
||||
return fmt.Sprintf("invalid send mode: %d", s)
|
||||
}
|
||||
|
|
226
vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go
generated
vendored
226
vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_handler.go
generated
vendored
|
@ -38,7 +38,7 @@ type packetNumberSpace struct {
|
|||
largestSent protocol.PacketNumber
|
||||
}
|
||||
|
||||
func newPacketNumberSpace(initialPN protocol.PacketNumber, skipPNs bool, rttStats *utils.RTTStats) *packetNumberSpace {
|
||||
func newPacketNumberSpace(initialPN protocol.PacketNumber, skipPNs bool) *packetNumberSpace {
|
||||
var pns packetNumberGenerator
|
||||
if skipPNs {
|
||||
pns = newSkippingPacketNumberGenerator(initialPN, protocol.SkipPacketInitialPeriod, protocol.SkipPacketMaxPeriod)
|
||||
|
@ -46,7 +46,7 @@ func newPacketNumberSpace(initialPN protocol.PacketNumber, skipPNs bool, rttStat
|
|||
pns = newSequentialPacketNumberGenerator(initialPN)
|
||||
}
|
||||
return &packetNumberSpace{
|
||||
history: newSentPacketHistory(rttStats),
|
||||
history: newSentPacketHistory(),
|
||||
pns: pns,
|
||||
largestSent: protocol.InvalidPacketNumber,
|
||||
largestAcked: protocol.InvalidPacketNumber,
|
||||
|
@ -75,7 +75,7 @@ type sentPacketHandler struct {
|
|||
// Only applies to the application-data packet number space.
|
||||
lowestNotConfirmedAcked protocol.PacketNumber
|
||||
|
||||
ackedPackets []*Packet // to avoid allocations in detectAndRemoveAckedPackets
|
||||
ackedPackets []*packet // to avoid allocations in detectAndRemoveAckedPackets
|
||||
|
||||
bytesInFlight protocol.ByteCount
|
||||
|
||||
|
@ -125,9 +125,9 @@ func newSentPacketHandler(
|
|||
return &sentPacketHandler{
|
||||
peerCompletedAddressValidation: pers == protocol.PerspectiveServer,
|
||||
peerAddressValidated: pers == protocol.PerspectiveClient || clientAddressValidated,
|
||||
initialPackets: newPacketNumberSpace(initialPN, false, rttStats),
|
||||
handshakePackets: newPacketNumberSpace(0, false, rttStats),
|
||||
appDataPackets: newPacketNumberSpace(0, true, rttStats),
|
||||
initialPackets: newPacketNumberSpace(initialPN, false),
|
||||
handshakePackets: newPacketNumberSpace(0, false),
|
||||
appDataPackets: newPacketNumberSpace(0, true),
|
||||
rttStats: rttStats,
|
||||
congestion: congestion,
|
||||
perspective: pers,
|
||||
|
@ -146,7 +146,7 @@ func (h *sentPacketHandler) DropPackets(encLevel protocol.EncryptionLevel) {
|
|||
h.dropPackets(encLevel)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) removeFromBytesInFlight(p *Packet) {
|
||||
func (h *sentPacketHandler) removeFromBytesInFlight(p *packet) {
|
||||
if p.includedInBytesInFlight {
|
||||
if p.Length > h.bytesInFlight {
|
||||
panic("negative bytes_in_flight")
|
||||
|
@ -165,7 +165,7 @@ func (h *sentPacketHandler) dropPackets(encLevel protocol.EncryptionLevel) {
|
|||
// remove outstanding packets from bytes_in_flight
|
||||
if encLevel == protocol.EncryptionInitial || encLevel == protocol.EncryptionHandshake {
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
pnSpace.history.Iterate(func(p *Packet) (bool, error) {
|
||||
pnSpace.history.Iterate(func(p *packet) (bool, error) {
|
||||
h.removeFromBytesInFlight(p)
|
||||
return true, nil
|
||||
})
|
||||
|
@ -182,8 +182,8 @@ func (h *sentPacketHandler) dropPackets(encLevel protocol.EncryptionLevel) {
|
|||
// and not when the client drops 0-RTT keys when the handshake completes.
|
||||
// When 0-RTT is rejected, all application data sent so far becomes invalid.
|
||||
// Delete the packets from the history and remove them from bytes_in_flight.
|
||||
h.appDataPackets.history.Iterate(func(p *Packet) (bool, error) {
|
||||
if p.EncryptionLevel != protocol.Encryption0RTT {
|
||||
h.appDataPackets.history.Iterate(func(p *packet) (bool, error) {
|
||||
if p.EncryptionLevel != protocol.Encryption0RTT && !p.skippedPacket {
|
||||
return false, nil
|
||||
}
|
||||
h.removeFromBytesInFlight(p)
|
||||
|
@ -228,26 +228,64 @@ func (h *sentPacketHandler) packetsInFlight() int {
|
|||
return packetsInFlight
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) SentPacket(p *Packet) {
|
||||
h.bytesSent += p.Length
|
||||
func (h *sentPacketHandler) SentPacket(
|
||||
t time.Time,
|
||||
pn, largestAcked protocol.PacketNumber,
|
||||
streamFrames []StreamFrame,
|
||||
frames []Frame,
|
||||
encLevel protocol.EncryptionLevel,
|
||||
size protocol.ByteCount,
|
||||
isPathMTUProbePacket bool,
|
||||
) {
|
||||
h.bytesSent += size
|
||||
// For the client, drop the Initial packet number space when the first Handshake packet is sent.
|
||||
if h.perspective == protocol.PerspectiveClient && p.EncryptionLevel == protocol.EncryptionHandshake && h.initialPackets != nil {
|
||||
if h.perspective == protocol.PerspectiveClient && encLevel == protocol.EncryptionHandshake && h.initialPackets != nil {
|
||||
h.dropPackets(protocol.EncryptionInitial)
|
||||
}
|
||||
isAckEliciting := h.sentPacketImpl(p)
|
||||
if isAckEliciting {
|
||||
h.getPacketNumberSpace(p.EncryptionLevel).history.SentAckElicitingPacket(p)
|
||||
} else {
|
||||
h.getPacketNumberSpace(p.EncryptionLevel).history.SentNonAckElicitingPacket(p.PacketNumber, p.EncryptionLevel, p.SendTime)
|
||||
putPacket(p)
|
||||
p = nil //nolint:ineffassign // This is just to be on the safe side.
|
||||
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
if h.logger.Debug() && pnSpace.history.HasOutstandingPackets() {
|
||||
for p := utils.Max(0, pnSpace.largestSent+1); p < pn; p++ {
|
||||
h.logger.Debugf("Skipping packet number %d", p)
|
||||
}
|
||||
}
|
||||
if h.tracer != nil && isAckEliciting {
|
||||
|
||||
pnSpace.largestSent = pn
|
||||
isAckEliciting := len(streamFrames) > 0 || len(frames) > 0
|
||||
|
||||
if isAckEliciting {
|
||||
pnSpace.lastAckElicitingPacketTime = t
|
||||
h.bytesInFlight += size
|
||||
if h.numProbesToSend > 0 {
|
||||
h.numProbesToSend--
|
||||
}
|
||||
}
|
||||
h.congestion.OnPacketSent(t, h.bytesInFlight, pn, size, isAckEliciting)
|
||||
|
||||
if !isAckEliciting {
|
||||
pnSpace.history.SentNonAckElicitingPacket(pn)
|
||||
if !h.peerCompletedAddressValidation {
|
||||
h.setLossDetectionTimer()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
p := getPacket()
|
||||
p.SendTime = t
|
||||
p.PacketNumber = pn
|
||||
p.EncryptionLevel = encLevel
|
||||
p.Length = size
|
||||
p.LargestAcked = largestAcked
|
||||
p.StreamFrames = streamFrames
|
||||
p.Frames = frames
|
||||
p.IsPathMTUProbePacket = isPathMTUProbePacket
|
||||
p.includedInBytesInFlight = true
|
||||
|
||||
pnSpace.history.SentAckElicitingPacket(p)
|
||||
if h.tracer != nil {
|
||||
h.tracer.UpdatedMetrics(h.rttStats, h.congestion.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight())
|
||||
}
|
||||
if isAckEliciting || !h.peerCompletedAddressValidation {
|
||||
h.setLossDetectionTimer()
|
||||
}
|
||||
h.setLossDetectionTimer()
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) getPacketNumberSpace(encLevel protocol.EncryptionLevel) *packetNumberSpace {
|
||||
|
@ -263,31 +301,6 @@ func (h *sentPacketHandler) getPacketNumberSpace(encLevel protocol.EncryptionLev
|
|||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* is ack-eliciting */ {
|
||||
pnSpace := h.getPacketNumberSpace(packet.EncryptionLevel)
|
||||
|
||||
if h.logger.Debug() && pnSpace.history.HasOutstandingPackets() {
|
||||
for p := utils.Max(0, pnSpace.largestSent+1); p < packet.PacketNumber; p++ {
|
||||
h.logger.Debugf("Skipping packet number %d", p)
|
||||
}
|
||||
}
|
||||
|
||||
pnSpace.largestSent = packet.PacketNumber
|
||||
isAckEliciting := len(packet.Frames) > 0
|
||||
|
||||
if isAckEliciting {
|
||||
pnSpace.lastAckElicitingPacketTime = packet.SendTime
|
||||
packet.includedInBytesInFlight = true
|
||||
h.bytesInFlight += packet.Length
|
||||
if h.numProbesToSend > 0 {
|
||||
h.numProbesToSend--
|
||||
}
|
||||
}
|
||||
h.congestion.OnPacketSent(packet.SendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isAckEliciting)
|
||||
|
||||
return isAckEliciting
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool /* contained 1-RTT packet */, error) {
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
|
||||
|
@ -361,7 +374,6 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En
|
|||
h.tracer.UpdatedMetrics(h.rttStats, h.congestion.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight())
|
||||
}
|
||||
|
||||
pnSpace.history.DeleteOldPackets(rcvTime)
|
||||
h.setLossDetectionTimer()
|
||||
return acked1RTTPacket, nil
|
||||
}
|
||||
|
@ -371,13 +383,13 @@ func (h *sentPacketHandler) GetLowestPacketNotConfirmedAcked() protocol.PacketNu
|
|||
}
|
||||
|
||||
// Packets are returned in ascending packet number order.
|
||||
func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encLevel protocol.EncryptionLevel) ([]*Packet, error) {
|
||||
func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encLevel protocol.EncryptionLevel) ([]*packet, error) {
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
h.ackedPackets = h.ackedPackets[:0]
|
||||
ackRangeIndex := 0
|
||||
lowestAcked := ack.LowestAcked()
|
||||
largestAcked := ack.LargestAcked()
|
||||
err := pnSpace.history.Iterate(func(p *Packet) (bool, error) {
|
||||
err := pnSpace.history.Iterate(func(p *packet) (bool, error) {
|
||||
// Ignore packets below the lowest acked
|
||||
if p.PacketNumber < lowestAcked {
|
||||
return true, nil
|
||||
|
@ -425,8 +437,13 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
|
|||
}
|
||||
|
||||
for _, f := range p.Frames {
|
||||
if f.OnAcked != nil {
|
||||
f.OnAcked(f.Frame)
|
||||
if f.Handler != nil {
|
||||
f.Handler.OnAcked(f.Frame)
|
||||
}
|
||||
}
|
||||
for _, f := range p.StreamFrames {
|
||||
if f.Handler != nil {
|
||||
f.Handler.OnAcked(f.Frame)
|
||||
}
|
||||
}
|
||||
if err := pnSpace.history.Remove(p.PacketNumber); err != nil {
|
||||
|
@ -587,30 +604,31 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.E
|
|||
lostSendTime := now.Add(-lossDelay)
|
||||
|
||||
priorInFlight := h.bytesInFlight
|
||||
return pnSpace.history.Iterate(func(p *Packet) (bool, error) {
|
||||
return pnSpace.history.Iterate(func(p *packet) (bool, error) {
|
||||
if p.PacketNumber > pnSpace.largestAcked {
|
||||
return false, nil
|
||||
}
|
||||
if p.declaredLost || p.skippedPacket {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var packetLost bool
|
||||
if p.SendTime.Before(lostSendTime) {
|
||||
packetLost = true
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("\tlost packet %d (time threshold)", p.PacketNumber)
|
||||
}
|
||||
if h.tracer != nil {
|
||||
h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossTimeThreshold)
|
||||
if !p.skippedPacket {
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("\tlost packet %d (time threshold)", p.PacketNumber)
|
||||
}
|
||||
if h.tracer != nil {
|
||||
h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossTimeThreshold)
|
||||
}
|
||||
}
|
||||
} else if pnSpace.largestAcked >= p.PacketNumber+packetThreshold {
|
||||
packetLost = true
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("\tlost packet %d (reordering threshold)", p.PacketNumber)
|
||||
}
|
||||
if h.tracer != nil {
|
||||
h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossReorderingThreshold)
|
||||
if !p.skippedPacket {
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("\tlost packet %d (reordering threshold)", p.PacketNumber)
|
||||
}
|
||||
if h.tracer != nil {
|
||||
h.tracer.LostPacket(p.EncryptionLevel, p.PacketNumber, logging.PacketLossReorderingThreshold)
|
||||
}
|
||||
}
|
||||
} else if pnSpace.lossTime.IsZero() {
|
||||
// Note: This conditional is only entered once per call
|
||||
|
@ -621,12 +639,14 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.E
|
|||
pnSpace.lossTime = lossTime
|
||||
}
|
||||
if packetLost {
|
||||
p = pnSpace.history.DeclareLost(p)
|
||||
// the bytes in flight need to be reduced no matter if the frames in this packet will be retransmitted
|
||||
h.removeFromBytesInFlight(p)
|
||||
h.queueFramesForRetransmission(p)
|
||||
if !p.IsPathMTUProbePacket {
|
||||
h.congestion.OnPacketLost(p.PacketNumber, p.Length, priorInFlight)
|
||||
pnSpace.history.DeclareLost(p.PacketNumber)
|
||||
if !p.skippedPacket {
|
||||
// the bytes in flight need to be reduced no matter if the frames in this packet will be retransmitted
|
||||
h.removeFromBytesInFlight(p)
|
||||
h.queueFramesForRetransmission(p)
|
||||
if !p.IsPathMTUProbePacket {
|
||||
h.congestion.OnPacketLost(p.PacketNumber, p.Length, priorInFlight)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
@ -689,7 +709,8 @@ func (h *sentPacketHandler) OnLossDetectionTimeout() error {
|
|||
h.ptoMode = SendPTOHandshake
|
||||
case protocol.Encryption1RTT:
|
||||
// skip a packet number in order to elicit an immediate ACK
|
||||
_ = h.PopPacketNumber(protocol.Encryption1RTT)
|
||||
pn := h.PopPacketNumber(protocol.Encryption1RTT)
|
||||
h.getPacketNumberSpace(protocol.Encryption1RTT).history.SkippedPacket(pn)
|
||||
h.ptoMode = SendPTOAppData
|
||||
default:
|
||||
return fmt.Errorf("PTO timer in unexpected encryption level: %s", encLevel)
|
||||
|
@ -703,23 +724,25 @@ func (h *sentPacketHandler) GetLossDetectionTimeout() time.Time {
|
|||
|
||||
func (h *sentPacketHandler) PeekPacketNumber(encLevel protocol.EncryptionLevel) (protocol.PacketNumber, protocol.PacketNumberLen) {
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
|
||||
var lowestUnacked protocol.PacketNumber
|
||||
if p := pnSpace.history.FirstOutstanding(); p != nil {
|
||||
lowestUnacked = p.PacketNumber
|
||||
} else {
|
||||
lowestUnacked = pnSpace.largestAcked + 1
|
||||
}
|
||||
|
||||
pn := pnSpace.pns.Peek()
|
||||
return pn, protocol.GetPacketNumberLengthForHeader(pn, lowestUnacked)
|
||||
// See section 17.1 of RFC 9000.
|
||||
return pn, protocol.GetPacketNumberLengthForHeader(pn, pnSpace.largestAcked)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) PopPacketNumber(encLevel protocol.EncryptionLevel) protocol.PacketNumber {
|
||||
return h.getPacketNumberSpace(encLevel).pns.Pop()
|
||||
pnSpace := h.getPacketNumberSpace(encLevel)
|
||||
skipped, pn := pnSpace.pns.Pop()
|
||||
if skipped {
|
||||
skippedPN := pn - 1
|
||||
pnSpace.history.SkippedPacket(skippedPN)
|
||||
if h.logger.Debug() {
|
||||
h.logger.Debugf("Skipping packet number %d", skippedPN)
|
||||
}
|
||||
}
|
||||
return pn
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) SendMode() SendMode {
|
||||
func (h *sentPacketHandler) SendMode(now time.Time) SendMode {
|
||||
numTrackedPackets := h.appDataPackets.history.Len()
|
||||
if h.initialPackets != nil {
|
||||
numTrackedPackets += h.initialPackets.history.Len()
|
||||
|
@ -758,6 +781,9 @@ func (h *sentPacketHandler) SendMode() SendMode {
|
|||
}
|
||||
return SendAck
|
||||
}
|
||||
if !h.congestion.HasPacingBudget(now) {
|
||||
return SendPacingLimited
|
||||
}
|
||||
return SendAny
|
||||
}
|
||||
|
||||
|
@ -765,10 +791,6 @@ func (h *sentPacketHandler) TimeUntilSend() time.Time {
|
|||
return h.congestion.TimeUntilSend(h.bytesInFlight)
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) HasPacingBudget() bool {
|
||||
return h.congestion.HasPacingBudget()
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) SetMaxDatagramSize(s protocol.ByteCount) {
|
||||
h.congestion.SetMaxDatagramSize(s)
|
||||
}
|
||||
|
@ -790,24 +812,32 @@ func (h *sentPacketHandler) QueueProbePacket(encLevel protocol.EncryptionLevel)
|
|||
// TODO: don't declare the packet lost here.
|
||||
// Keep track of acknowledged frames instead.
|
||||
h.removeFromBytesInFlight(p)
|
||||
pnSpace.history.DeclareLost(p)
|
||||
pnSpace.history.DeclareLost(p.PacketNumber)
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) queueFramesForRetransmission(p *Packet) {
|
||||
if len(p.Frames) == 0 {
|
||||
func (h *sentPacketHandler) queueFramesForRetransmission(p *packet) {
|
||||
if len(p.Frames) == 0 && len(p.StreamFrames) == 0 {
|
||||
panic("no frames")
|
||||
}
|
||||
for _, f := range p.Frames {
|
||||
f.OnLost(f.Frame)
|
||||
if f.Handler != nil {
|
||||
f.Handler.OnLost(f.Frame)
|
||||
}
|
||||
}
|
||||
for _, f := range p.StreamFrames {
|
||||
if f.Handler != nil {
|
||||
f.Handler.OnLost(f.Frame)
|
||||
}
|
||||
}
|
||||
p.StreamFrames = nil
|
||||
p.Frames = nil
|
||||
}
|
||||
|
||||
func (h *sentPacketHandler) ResetForRetry() error {
|
||||
h.bytesInFlight = 0
|
||||
var firstPacketSendTime time.Time
|
||||
h.initialPackets.history.Iterate(func(p *Packet) (bool, error) {
|
||||
h.initialPackets.history.Iterate(func(p *packet) (bool, error) {
|
||||
if firstPacketSendTime.IsZero() {
|
||||
firstPacketSendTime = p.SendTime
|
||||
}
|
||||
|
@ -819,7 +849,7 @@ func (h *sentPacketHandler) ResetForRetry() error {
|
|||
})
|
||||
// All application data packets sent at this point are 0-RTT packets.
|
||||
// In the case of a Retry, we can assume that the server dropped all of them.
|
||||
h.appDataPackets.history.Iterate(func(p *Packet) (bool, error) {
|
||||
h.appDataPackets.history.Iterate(func(p *packet) (bool, error) {
|
||||
if !p.declaredLost && !p.skippedPacket {
|
||||
h.queueFramesForRetransmission(p)
|
||||
}
|
||||
|
@ -839,8 +869,8 @@ func (h *sentPacketHandler) ResetForRetry() error {
|
|||
h.tracer.UpdatedMetrics(h.rttStats, h.congestion.GetCongestionWindow(), h.bytesInFlight, h.packetsInFlight())
|
||||
}
|
||||
}
|
||||
h.initialPackets = newPacketNumberSpace(h.initialPackets.pns.Pop(), false, h.rttStats)
|
||||
h.appDataPackets = newPacketNumberSpace(h.appDataPackets.pns.Pop(), true, h.rttStats)
|
||||
h.initialPackets = newPacketNumberSpace(h.initialPackets.pns.Peek(), false)
|
||||
h.appDataPackets = newPacketNumberSpace(h.appDataPackets.pns.Peek(), true)
|
||||
oldAlarm := h.alarm
|
||||
h.alarm = time.Time{}
|
||||
if h.tracer != nil {
|
||||
|
|
248
vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go
generated
vendored
248
vendor/github.com/quic-go/quic-go/internal/ackhandler/sent_packet_history.go
generated
vendored
|
@ -2,162 +2,176 @@ package ackhandler
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
list "github.com/quic-go/quic-go/internal/utils/linkedlist"
|
||||
)
|
||||
|
||||
type sentPacketHistory struct {
|
||||
rttStats *utils.RTTStats
|
||||
outstandingPacketList *list.List[*Packet]
|
||||
etcPacketList *list.List[*Packet]
|
||||
packetMap map[protocol.PacketNumber]*list.Element[*Packet]
|
||||
highestSent protocol.PacketNumber
|
||||
packets []*packet
|
||||
|
||||
numOutstanding int
|
||||
|
||||
highestPacketNumber protocol.PacketNumber
|
||||
}
|
||||
|
||||
var packetElementPool sync.Pool
|
||||
|
||||
func init() {
|
||||
packetElementPool = *list.NewPool[*Packet]()
|
||||
}
|
||||
|
||||
func newSentPacketHistory(rttStats *utils.RTTStats) *sentPacketHistory {
|
||||
func newSentPacketHistory() *sentPacketHistory {
|
||||
return &sentPacketHistory{
|
||||
rttStats: rttStats,
|
||||
outstandingPacketList: list.NewWithPool[*Packet](&packetElementPool),
|
||||
etcPacketList: list.NewWithPool[*Packet](&packetElementPool),
|
||||
packetMap: make(map[protocol.PacketNumber]*list.Element[*Packet]),
|
||||
highestSent: protocol.InvalidPacketNumber,
|
||||
packets: make([]*packet, 0, 32),
|
||||
highestPacketNumber: protocol.InvalidPacketNumber,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel, t time.Time) {
|
||||
h.registerSentPacket(pn, encLevel, t)
|
||||
func (h *sentPacketHistory) checkSequentialPacketNumberUse(pn protocol.PacketNumber) {
|
||||
if h.highestPacketNumber != protocol.InvalidPacketNumber {
|
||||
if pn != h.highestPacketNumber+1 {
|
||||
panic("non-sequential packet number use")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) SentAckElicitingPacket(p *Packet) {
|
||||
h.registerSentPacket(p.PacketNumber, p.EncryptionLevel, p.SendTime)
|
||||
func (h *sentPacketHistory) SkippedPacket(pn protocol.PacketNumber) {
|
||||
h.checkSequentialPacketNumberUse(pn)
|
||||
h.highestPacketNumber = pn
|
||||
h.packets = append(h.packets, &packet{
|
||||
PacketNumber: pn,
|
||||
skippedPacket: true,
|
||||
})
|
||||
}
|
||||
|
||||
var el *list.Element[*Packet]
|
||||
func (h *sentPacketHistory) SentNonAckElicitingPacket(pn protocol.PacketNumber) {
|
||||
h.checkSequentialPacketNumberUse(pn)
|
||||
h.highestPacketNumber = pn
|
||||
if len(h.packets) > 0 {
|
||||
h.packets = append(h.packets, nil)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) SentAckElicitingPacket(p *packet) {
|
||||
h.checkSequentialPacketNumberUse(p.PacketNumber)
|
||||
h.highestPacketNumber = p.PacketNumber
|
||||
h.packets = append(h.packets, p)
|
||||
if p.outstanding() {
|
||||
el = h.outstandingPacketList.PushBack(p)
|
||||
} else {
|
||||
el = h.etcPacketList.PushBack(p)
|
||||
h.numOutstanding++
|
||||
}
|
||||
h.packetMap[p.PacketNumber] = el
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) registerSentPacket(pn protocol.PacketNumber, encLevel protocol.EncryptionLevel, t time.Time) {
|
||||
if pn <= h.highestSent {
|
||||
panic("non-sequential packet number use")
|
||||
}
|
||||
// Skipped packet numbers.
|
||||
for p := h.highestSent + 1; p < pn; p++ {
|
||||
el := h.etcPacketList.PushBack(&Packet{
|
||||
PacketNumber: p,
|
||||
EncryptionLevel: encLevel,
|
||||
SendTime: t,
|
||||
skippedPacket: true,
|
||||
})
|
||||
h.packetMap[p] = el
|
||||
}
|
||||
h.highestSent = pn
|
||||
}
|
||||
|
||||
// Iterate iterates through all packets.
|
||||
func (h *sentPacketHistory) Iterate(cb func(*Packet) (cont bool, err error)) error {
|
||||
cont := true
|
||||
outstandingEl := h.outstandingPacketList.Front()
|
||||
etcEl := h.etcPacketList.Front()
|
||||
var el *list.Element[*Packet]
|
||||
// whichever has the next packet number is returned first
|
||||
for cont {
|
||||
if outstandingEl == nil || (etcEl != nil && etcEl.Value.PacketNumber < outstandingEl.Value.PacketNumber) {
|
||||
el = etcEl
|
||||
} else {
|
||||
el = outstandingEl
|
||||
func (h *sentPacketHistory) Iterate(cb func(*packet) (cont bool, err error)) error {
|
||||
for _, p := range h.packets {
|
||||
if p == nil {
|
||||
continue
|
||||
}
|
||||
if el == nil {
|
||||
return nil
|
||||
}
|
||||
if el == outstandingEl {
|
||||
outstandingEl = outstandingEl.Next()
|
||||
} else {
|
||||
etcEl = etcEl.Next()
|
||||
}
|
||||
var err error
|
||||
cont, err = cb(el.Value)
|
||||
cont, err := cb(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !cont {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FirstOutstanding returns the first outstanding packet.
|
||||
func (h *sentPacketHistory) FirstOutstanding() *Packet {
|
||||
el := h.outstandingPacketList.Front()
|
||||
if el == nil {
|
||||
func (h *sentPacketHistory) FirstOutstanding() *packet {
|
||||
if !h.HasOutstandingPackets() {
|
||||
return nil
|
||||
}
|
||||
return el.Value
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) Len() int {
|
||||
return len(h.packetMap)
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) Remove(p protocol.PacketNumber) error {
|
||||
el, ok := h.packetMap[p]
|
||||
if !ok {
|
||||
return fmt.Errorf("packet %d not found in sent packet history", p)
|
||||
for _, p := range h.packets {
|
||||
if p != nil && p.outstanding() {
|
||||
return p
|
||||
}
|
||||
}
|
||||
el.List().Remove(el)
|
||||
delete(h.packetMap, p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) HasOutstandingPackets() bool {
|
||||
return h.outstandingPacketList.Len() > 0
|
||||
func (h *sentPacketHistory) Len() int {
|
||||
return len(h.packets)
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) DeleteOldPackets(now time.Time) {
|
||||
maxAge := 3 * h.rttStats.PTO(false)
|
||||
var nextEl *list.Element[*Packet]
|
||||
// we don't iterate outstandingPacketList, as we should not delete outstanding packets.
|
||||
// being outstanding for more than 3*PTO should only happen in the case of drastic RTT changes.
|
||||
for el := h.etcPacketList.Front(); el != nil; el = nextEl {
|
||||
nextEl = el.Next()
|
||||
p := el.Value
|
||||
if p.SendTime.After(now.Add(-maxAge)) {
|
||||
break
|
||||
}
|
||||
delete(h.packetMap, p.PacketNumber)
|
||||
h.etcPacketList.Remove(el)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) DeclareLost(p *Packet) *Packet {
|
||||
el, ok := h.packetMap[p.PacketNumber]
|
||||
func (h *sentPacketHistory) Remove(pn protocol.PacketNumber) error {
|
||||
idx, ok := h.getIndex(pn)
|
||||
if !ok {
|
||||
return nil
|
||||
return fmt.Errorf("packet %d not found in sent packet history", pn)
|
||||
}
|
||||
el.List().Remove(el)
|
||||
p.declaredLost = true
|
||||
// move it to the correct position in the etc list (based on the packet number)
|
||||
for el = h.etcPacketList.Back(); el != nil; el = el.Prev() {
|
||||
if el.Value.PacketNumber < p.PacketNumber {
|
||||
break
|
||||
p := h.packets[idx]
|
||||
if p.outstanding() {
|
||||
h.numOutstanding--
|
||||
if h.numOutstanding < 0 {
|
||||
panic("negative number of outstanding packets")
|
||||
}
|
||||
}
|
||||
if el == nil {
|
||||
el = h.etcPacketList.PushFront(p)
|
||||
} else {
|
||||
el = h.etcPacketList.InsertAfter(p, el)
|
||||
h.packets[idx] = nil
|
||||
// clean up all skipped packets directly before this packet number
|
||||
for idx > 0 {
|
||||
idx--
|
||||
p := h.packets[idx]
|
||||
if p == nil || !p.skippedPacket {
|
||||
break
|
||||
}
|
||||
h.packets[idx] = nil
|
||||
}
|
||||
if idx == 0 {
|
||||
h.cleanupStart()
|
||||
}
|
||||
if len(h.packets) > 0 && h.packets[0] == nil {
|
||||
panic("remove failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getIndex gets the index of packet p in the packets slice.
|
||||
func (h *sentPacketHistory) getIndex(p protocol.PacketNumber) (int, bool) {
|
||||
if len(h.packets) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
first := h.packets[0].PacketNumber
|
||||
if p < first {
|
||||
return 0, false
|
||||
}
|
||||
index := int(p - first)
|
||||
if index > len(h.packets)-1 {
|
||||
return 0, false
|
||||
}
|
||||
return index, true
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) HasOutstandingPackets() bool {
|
||||
return h.numOutstanding > 0
|
||||
}
|
||||
|
||||
// delete all nil entries at the beginning of the packets slice
|
||||
func (h *sentPacketHistory) cleanupStart() {
|
||||
for i, p := range h.packets {
|
||||
if p != nil {
|
||||
h.packets = h.packets[i:]
|
||||
return
|
||||
}
|
||||
}
|
||||
h.packets = h.packets[:0]
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) LowestPacketNumber() protocol.PacketNumber {
|
||||
if len(h.packets) == 0 {
|
||||
return protocol.InvalidPacketNumber
|
||||
}
|
||||
return h.packets[0].PacketNumber
|
||||
}
|
||||
|
||||
func (h *sentPacketHistory) DeclareLost(pn protocol.PacketNumber) {
|
||||
idx, ok := h.getIndex(pn)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
p := h.packets[idx]
|
||||
if p.outstanding() {
|
||||
h.numOutstanding--
|
||||
if h.numOutstanding < 0 {
|
||||
panic("negative number of outstanding packets")
|
||||
}
|
||||
}
|
||||
h.packets[idx] = nil
|
||||
if idx == 0 {
|
||||
h.cleanupStart()
|
||||
}
|
||||
h.packetMap[p.PacketNumber] = el
|
||||
return el.Value
|
||||
}
|
||||
|
|
4
vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go
generated
vendored
4
vendor/github.com/quic-go/quic-go/internal/congestion/cubic_sender.go
generated
vendored
|
@ -120,8 +120,8 @@ func (c *cubicSender) TimeUntilSend(_ protocol.ByteCount) time.Time {
|
|||
return c.pacer.TimeUntilSend()
|
||||
}
|
||||
|
||||
func (c *cubicSender) HasPacingBudget() bool {
|
||||
return c.pacer.Budget(c.clock.Now()) >= c.maxDatagramSize
|
||||
func (c *cubicSender) HasPacingBudget(now time.Time) bool {
|
||||
return c.pacer.Budget(now) >= c.maxDatagramSize
|
||||
}
|
||||
|
||||
func (c *cubicSender) maxCongestionWindow() protocol.ByteCount {
|
||||
|
|
2
vendor/github.com/quic-go/quic-go/internal/congestion/interface.go
generated
vendored
2
vendor/github.com/quic-go/quic-go/internal/congestion/interface.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
|||
// A SendAlgorithm performs congestion control
|
||||
type SendAlgorithm interface {
|
||||
TimeUntilSend(bytesInFlight protocol.ByteCount) time.Time
|
||||
HasPacingBudget() bool
|
||||
HasPacingBudget(now time.Time) bool
|
||||
OnPacketSent(sentTime time.Time, bytesInFlight protocol.ByteCount, packetNumber protocol.PacketNumber, bytes protocol.ByteCount, isRetransmittable bool)
|
||||
CanSend(bytesInFlight protocol.ByteCount) bool
|
||||
MaybeExitSlowStart()
|
||||
|
|
5
vendor/github.com/quic-go/quic-go/internal/protocol/protocol.go
generated
vendored
5
vendor/github.com/quic-go/quic-go/internal/protocol/protocol.go
generated
vendored
|
@ -59,7 +59,10 @@ type StatelessResetToken [16]byte
|
|||
// ethernet's max size, minus the IP and UDP headers. IPv6 has a 40 byte header,
|
||||
// UDP adds an additional 8 bytes. This is a total overhead of 48 bytes.
|
||||
// Ethernet's max packet size is 1500 bytes, 1500 - 48 = 1452.
|
||||
const MaxPacketBufferSize ByteCount = 1452
|
||||
const MaxPacketBufferSize = 1452
|
||||
|
||||
// MaxLargePacketBufferSize is used when using GSO
|
||||
const MaxLargePacketBufferSize = 20 * 1024
|
||||
|
||||
// MinInitialPacketSize is the minimum size an Initial packet is required to have.
|
||||
const MinInitialPacketSize = 1200
|
||||
|
|
86
vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go
generated
vendored
Normal file
86
vendor/github.com/quic-go/quic-go/internal/utils/ringbuffer/ringbuffer.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package ringbuffer
|
||||
|
||||
// A RingBuffer is a ring buffer.
|
||||
// It acts as a heap that doesn't cause any allocations.
|
||||
type RingBuffer[T any] struct {
|
||||
ring []T
|
||||
headPos, tailPos int
|
||||
full bool
|
||||
}
|
||||
|
||||
// Init preallocs a buffer with a certain size.
|
||||
func (r *RingBuffer[T]) Init(size int) {
|
||||
r.ring = make([]T, size)
|
||||
}
|
||||
|
||||
// Len returns the number of elements in the ring buffer.
|
||||
func (r *RingBuffer[T]) Len() int {
|
||||
if r.full {
|
||||
return len(r.ring)
|
||||
}
|
||||
if r.tailPos >= r.headPos {
|
||||
return r.tailPos - r.headPos
|
||||
}
|
||||
return r.tailPos - r.headPos + len(r.ring)
|
||||
}
|
||||
|
||||
// Empty says if the ring buffer is empty.
|
||||
func (r *RingBuffer[T]) Empty() bool {
|
||||
return !r.full && r.headPos == r.tailPos
|
||||
}
|
||||
|
||||
// PushBack adds a new element.
|
||||
// If the ring buffer is full, its capacity is increased first.
|
||||
func (r *RingBuffer[T]) PushBack(t T) {
|
||||
if r.full || len(r.ring) == 0 {
|
||||
r.grow()
|
||||
}
|
||||
r.ring[r.tailPos] = t
|
||||
r.tailPos++
|
||||
if r.tailPos == len(r.ring) {
|
||||
r.tailPos = 0
|
||||
}
|
||||
if r.tailPos == r.headPos {
|
||||
r.full = true
|
||||
}
|
||||
}
|
||||
|
||||
// PopFront returns the next element.
|
||||
// It must not be called when the buffer is empty, that means that
|
||||
// callers might need to check if there are elements in the buffer first.
|
||||
func (r *RingBuffer[T]) PopFront() T {
|
||||
if r.Empty() {
|
||||
panic("github.com/quic-go/quic-go/internal/utils/ringbuffer: pop from an empty queue")
|
||||
}
|
||||
r.full = false
|
||||
t := r.ring[r.headPos]
|
||||
r.ring[r.headPos] = *new(T)
|
||||
r.headPos++
|
||||
if r.headPos == len(r.ring) {
|
||||
r.headPos = 0
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Grow the maximum size of the queue.
|
||||
// This method assume the queue is full.
|
||||
func (r *RingBuffer[T]) grow() {
|
||||
oldRing := r.ring
|
||||
newSize := len(oldRing) * 2
|
||||
if newSize == 0 {
|
||||
newSize = 1
|
||||
}
|
||||
r.ring = make([]T, newSize)
|
||||
headLen := copy(r.ring, oldRing[r.headPos:])
|
||||
copy(r.ring[headLen:], oldRing[:r.headPos])
|
||||
r.headPos, r.tailPos, r.full = 0, len(oldRing), false
|
||||
}
|
||||
|
||||
// Clear removes all elements.
|
||||
func (r *RingBuffer[T]) Clear() {
|
||||
var zeroValue T
|
||||
for i := range r.ring {
|
||||
r.ring[i] = zeroValue
|
||||
}
|
||||
r.headPos, r.tailPos, r.full = 0, 0, false
|
||||
}
|
44
vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go
generated
vendored
44
vendor/github.com/quic-go/quic-go/internal/wire/ack_frame.go
generated
vendored
|
@ -22,19 +22,17 @@ type AckFrame struct {
|
|||
}
|
||||
|
||||
// parseAckFrame reads an ACK frame
|
||||
func parseAckFrame(r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.VersionNumber) (*AckFrame, error) {
|
||||
func parseAckFrame(frame *AckFrame, r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.VersionNumber) error {
|
||||
ecn := typ == ackECNFrameType
|
||||
|
||||
frame := GetAckFrame()
|
||||
|
||||
la, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
largestAcked := protocol.PacketNumber(la)
|
||||
delay, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
delayTime := time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
|
||||
|
@ -46,17 +44,17 @@ func parseAckFrame(r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protoc
|
|||
|
||||
numBlocks, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// read the first ACK range
|
||||
ab, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
ackBlock := protocol.PacketNumber(ab)
|
||||
if ackBlock > largestAcked {
|
||||
return nil, errors.New("invalid first ACK range")
|
||||
return errors.New("invalid first ACK range")
|
||||
}
|
||||
smallest := largestAcked - ackBlock
|
||||
|
||||
|
@ -65,50 +63,50 @@ func parseAckFrame(r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protoc
|
|||
for i := uint64(0); i < numBlocks; i++ {
|
||||
g, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
gap := protocol.PacketNumber(g)
|
||||
if smallest < gap+2 {
|
||||
return nil, errInvalidAckRanges
|
||||
return errInvalidAckRanges
|
||||
}
|
||||
largest := smallest - gap - 2
|
||||
|
||||
ab, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
ackBlock := protocol.PacketNumber(ab)
|
||||
|
||||
if ackBlock > largest {
|
||||
return nil, errInvalidAckRanges
|
||||
return errInvalidAckRanges
|
||||
}
|
||||
smallest = largest - ackBlock
|
||||
frame.AckRanges = append(frame.AckRanges, AckRange{Smallest: smallest, Largest: largest})
|
||||
}
|
||||
|
||||
if !frame.validateAckRanges() {
|
||||
return nil, errInvalidAckRanges
|
||||
return errInvalidAckRanges
|
||||
}
|
||||
|
||||
if ecn {
|
||||
ect0, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
frame.ECT0 = ect0
|
||||
ect1, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
frame.ECT1 = ect1
|
||||
ecnce, err := quicvarint.Read(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
frame.ECNCE = ecnce
|
||||
}
|
||||
|
||||
return frame, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append appends an ACK frame.
|
||||
|
@ -251,6 +249,18 @@ func (f *AckFrame) AcksPacket(p protocol.PacketNumber) bool {
|
|||
return p <= f.AckRanges[i].Largest
|
||||
}
|
||||
|
||||
func (f *AckFrame) Reset() {
|
||||
f.DelayTime = 0
|
||||
f.ECT0 = 0
|
||||
f.ECT1 = 0
|
||||
f.ECNCE = 0
|
||||
for _, r := range f.AckRanges {
|
||||
r.Largest = 0
|
||||
r.Smallest = 0
|
||||
}
|
||||
f.AckRanges = f.AckRanges[:0]
|
||||
}
|
||||
|
||||
func encodeAckDelay(delay time.Duration) uint64 {
|
||||
return uint64(delay.Nanoseconds() / (1000 * (1 << protocol.AckDelayExponent)))
|
||||
}
|
||||
|
|
24
vendor/github.com/quic-go/quic-go/internal/wire/ack_frame_pool.go
generated
vendored
24
vendor/github.com/quic-go/quic-go/internal/wire/ack_frame_pool.go
generated
vendored
|
@ -1,24 +0,0 @@
|
|||
package wire
|
||||
|
||||
import "sync"
|
||||
|
||||
var ackFramePool = sync.Pool{New: func() any {
|
||||
return &AckFrame{}
|
||||
}}
|
||||
|
||||
func GetAckFrame() *AckFrame {
|
||||
f := ackFramePool.Get().(*AckFrame)
|
||||
f.AckRanges = f.AckRanges[:0]
|
||||
f.ECNCE = 0
|
||||
f.ECT0 = 0
|
||||
f.ECT1 = 0
|
||||
f.DelayTime = 0
|
||||
return f
|
||||
}
|
||||
|
||||
func PutAckFrame(f *AckFrame) {
|
||||
if cap(f.AckRanges) > 4 {
|
||||
return
|
||||
}
|
||||
ackFramePool.Put(f)
|
||||
}
|
12
vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go
generated
vendored
12
vendor/github.com/quic-go/quic-go/internal/wire/frame_parser.go
generated
vendored
|
@ -39,9 +39,12 @@ const (
|
|||
type frameParser struct {
|
||||
r bytes.Reader // cached bytes.Reader, so we don't have to repeatedly allocate them
|
||||
|
||||
ackDelayExponent uint8
|
||||
|
||||
ackDelayExponent uint8
|
||||
supportsDatagrams bool
|
||||
|
||||
// To avoid allocating when parsing, keep a single ACK frame struct.
|
||||
// It is used over and over again.
|
||||
ackFrame *AckFrame
|
||||
}
|
||||
|
||||
var _ FrameParser = &frameParser{}
|
||||
|
@ -51,6 +54,7 @@ func NewFrameParser(supportsDatagrams bool) *frameParser {
|
|||
return &frameParser{
|
||||
r: *bytes.NewReader(nil),
|
||||
supportsDatagrams: supportsDatagrams,
|
||||
ackFrame: &AckFrame{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +109,9 @@ func (p *frameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.
|
|||
if encLevel != protocol.Encryption1RTT {
|
||||
ackDelayExponent = protocol.DefaultAckDelayExponent
|
||||
}
|
||||
frame, err = parseAckFrame(r, typ, ackDelayExponent, v)
|
||||
p.ackFrame.Reset()
|
||||
err = parseAckFrame(p.ackFrame, r, typ, ackDelayExponent, v)
|
||||
frame = p.ackFrame
|
||||
case resetStreamFrameType:
|
||||
frame, err = parseResetStreamFrame(r, v)
|
||||
case stopSendingFrameType:
|
||||
|
|
23
vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go
generated
vendored
23
vendor/github.com/quic-go/quic-go/internal/wire/transport_parameters.go
generated
vendored
|
@ -2,14 +2,13 @@ package wire
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
|
@ -26,15 +25,6 @@ var AdditionalTransportParametersClient map[uint64][]byte
|
|||
|
||||
const transportParameterMarshalingVersion = 1
|
||||
|
||||
var (
|
||||
randomMutex sync.Mutex
|
||||
random rand.Rand
|
||||
)
|
||||
|
||||
func init() {
|
||||
random = *rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
}
|
||||
|
||||
type transportParameterID uint64
|
||||
|
||||
const (
|
||||
|
@ -341,13 +331,12 @@ func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte {
|
|||
b := make([]byte, 0, 256)
|
||||
|
||||
// add a greased value
|
||||
b = quicvarint.Append(b, uint64(27+31*rand.Intn(100)))
|
||||
randomMutex.Lock()
|
||||
length := random.Intn(16)
|
||||
random := make([]byte, 18)
|
||||
rand.Read(random)
|
||||
b = quicvarint.Append(b, 27+31*uint64(random[0]))
|
||||
length := random[1] % 16
|
||||
b = quicvarint.Append(b, uint64(length))
|
||||
b = b[:len(b)+length]
|
||||
random.Read(b[len(b)-length:])
|
||||
randomMutex.Unlock()
|
||||
b = append(b, random[2:2+length]...)
|
||||
|
||||
// initial_max_stream_data_bidi_local
|
||||
b = p.marshalVarintParam(b, initialMaxStreamDataBidiLocalParameterID, uint64(p.InitialMaxStreamDataBidiLocal))
|
||||
|
|
83
vendor/github.com/quic-go/quic-go/mtu_discoverer.go
generated
vendored
83
vendor/github.com/quic-go/quic-go/mtu_discoverer.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/ackhandler"
|
||||
|
@ -10,7 +11,11 @@ import (
|
|||
)
|
||||
|
||||
type mtuDiscoverer interface {
|
||||
// Start starts the MTU discovery process.
|
||||
// It's unnecessary to call ShouldSendProbe before that.
|
||||
Start(maxPacketSize protocol.ByteCount)
|
||||
ShouldSendProbe(now time.Time) bool
|
||||
CurrentSize() protocol.ByteCount
|
||||
GetPing() (ping ackhandler.Frame, datagramSize protocol.ByteCount)
|
||||
}
|
||||
|
||||
|
@ -22,25 +27,38 @@ const (
|
|||
mtuProbeDelay = 5
|
||||
)
|
||||
|
||||
func getMaxPacketSize(addr net.Addr) protocol.ByteCount {
|
||||
maxSize := protocol.ByteCount(protocol.MinInitialPacketSize)
|
||||
// If this is not a UDP address, we don't know anything about the MTU.
|
||||
// Use the minimum size of an Initial packet as the max packet size.
|
||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
if utils.IsIPv4(udpAddr.IP) {
|
||||
maxSize = protocol.InitialPacketSizeIPv4
|
||||
} else {
|
||||
maxSize = protocol.InitialPacketSizeIPv6
|
||||
}
|
||||
}
|
||||
return maxSize
|
||||
}
|
||||
|
||||
type mtuFinder struct {
|
||||
lastProbeTime time.Time
|
||||
probeInFlight bool
|
||||
mtuIncreased func(protocol.ByteCount)
|
||||
|
||||
rttStats *utils.RTTStats
|
||||
inFlight protocol.ByteCount // the size of the probe packet currently in flight. InvalidByteCount if none is in flight
|
||||
current protocol.ByteCount
|
||||
max protocol.ByteCount // the maximum value, as advertised by the peer (or our maximum size buffer)
|
||||
}
|
||||
|
||||
var _ mtuDiscoverer = &mtuFinder{}
|
||||
|
||||
func newMTUDiscoverer(rttStats *utils.RTTStats, start, max protocol.ByteCount, mtuIncreased func(protocol.ByteCount)) mtuDiscoverer {
|
||||
func newMTUDiscoverer(rttStats *utils.RTTStats, start protocol.ByteCount, mtuIncreased func(protocol.ByteCount)) *mtuFinder {
|
||||
return &mtuFinder{
|
||||
current: start,
|
||||
rttStats: rttStats,
|
||||
lastProbeTime: time.Now(), // to make sure the first probe packet is not sent immediately
|
||||
mtuIncreased: mtuIncreased,
|
||||
max: max,
|
||||
inFlight: protocol.InvalidByteCount,
|
||||
current: start,
|
||||
rttStats: rttStats,
|
||||
mtuIncreased: mtuIncreased,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,8 +66,16 @@ func (f *mtuFinder) done() bool {
|
|||
return f.max-f.current <= maxMTUDiff+1
|
||||
}
|
||||
|
||||
func (f *mtuFinder) Start(maxPacketSize protocol.ByteCount) {
|
||||
f.lastProbeTime = time.Now() // makes sure the first probe packet is not sent immediately
|
||||
f.max = maxPacketSize
|
||||
}
|
||||
|
||||
func (f *mtuFinder) ShouldSendProbe(now time.Time) bool {
|
||||
if f.probeInFlight || f.done() {
|
||||
if f.max == 0 || f.lastProbeTime.IsZero() {
|
||||
return false
|
||||
}
|
||||
if f.inFlight != protocol.InvalidByteCount || f.done() {
|
||||
return false
|
||||
}
|
||||
return !now.Before(f.lastProbeTime.Add(mtuProbeDelay * f.rttStats.SmoothedRTT()))
|
||||
|
@ -58,17 +84,36 @@ func (f *mtuFinder) ShouldSendProbe(now time.Time) bool {
|
|||
func (f *mtuFinder) GetPing() (ackhandler.Frame, protocol.ByteCount) {
|
||||
size := (f.max + f.current) / 2
|
||||
f.lastProbeTime = time.Now()
|
||||
f.probeInFlight = true
|
||||
f.inFlight = size
|
||||
return ackhandler.Frame{
|
||||
Frame: &wire.PingFrame{},
|
||||
OnLost: func(wire.Frame) {
|
||||
f.probeInFlight = false
|
||||
f.max = size
|
||||
},
|
||||
OnAcked: func(wire.Frame) {
|
||||
f.probeInFlight = false
|
||||
f.current = size
|
||||
f.mtuIncreased(size)
|
||||
},
|
||||
Frame: &wire.PingFrame{},
|
||||
Handler: (*mtuFinderAckHandler)(f),
|
||||
}, size
|
||||
}
|
||||
|
||||
func (f *mtuFinder) CurrentSize() protocol.ByteCount {
|
||||
return f.current
|
||||
}
|
||||
|
||||
type mtuFinderAckHandler mtuFinder
|
||||
|
||||
var _ ackhandler.FrameHandler = &mtuFinderAckHandler{}
|
||||
|
||||
func (h *mtuFinderAckHandler) OnAcked(wire.Frame) {
|
||||
size := h.inFlight
|
||||
if size == protocol.InvalidByteCount {
|
||||
panic("OnAcked callback called although there's no MTU probe packet in flight")
|
||||
}
|
||||
h.inFlight = protocol.InvalidByteCount
|
||||
h.current = size
|
||||
h.mtuIncreased(size)
|
||||
}
|
||||
|
||||
func (h *mtuFinderAckHandler) OnLost(wire.Frame) {
|
||||
size := h.inFlight
|
||||
if size == protocol.InvalidByteCount {
|
||||
panic("OnLost callback called although there's no MTU probe packet in flight")
|
||||
}
|
||||
h.max = size
|
||||
h.inFlight = protocol.InvalidByteCount
|
||||
}
|
||||
|
|
22
vendor/github.com/quic-go/quic-go/packet_handler_map.go
generated
vendored
22
vendor/github.com/quic-go/quic-go/packet_handler_map.go
generated
vendored
|
@ -15,23 +15,35 @@ import (
|
|||
"github.com/quic-go/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
type connCapabilities struct {
|
||||
// This connection has the Don't Fragment (DF) bit set.
|
||||
// This means it makes to run DPLPMTUD.
|
||||
DF bool
|
||||
// GSO (Generic Segmentation Offload) supported
|
||||
GSO bool
|
||||
}
|
||||
|
||||
// rawConn is a connection that allow reading of a receivedPackeh.
|
||||
type rawConn interface {
|
||||
ReadPacket() (*receivedPacket, error)
|
||||
WritePacket(b []byte, addr net.Addr, oob []byte) (int, error)
|
||||
ReadPacket() (receivedPacket, error)
|
||||
// The size parameter is used for GSO.
|
||||
// If GSO is not support, len(b) must be equal to size.
|
||||
WritePacket(b []byte, size uint16, addr net.Addr, oob []byte) (int, error)
|
||||
LocalAddr() net.Addr
|
||||
SetReadDeadline(time.Time) error
|
||||
io.Closer
|
||||
|
||||
capabilities() connCapabilities
|
||||
}
|
||||
|
||||
type closePacket struct {
|
||||
payload []byte
|
||||
addr net.Addr
|
||||
info *packetInfo
|
||||
info packetInfo
|
||||
}
|
||||
|
||||
type unknownPacketHandler interface {
|
||||
handlePacket(*receivedPacket)
|
||||
handlePacket(receivedPacket)
|
||||
setCloseError(error)
|
||||
}
|
||||
|
||||
|
@ -165,7 +177,7 @@ func (h *packetHandlerMap) ReplaceWithClosed(ids []protocol.ConnectionID, pers p
|
|||
var handler packetHandler
|
||||
if connClosePacket != nil {
|
||||
handler = newClosedLocalConn(
|
||||
func(addr net.Addr, info *packetInfo) {
|
||||
func(addr net.Addr, info packetInfo) {
|
||||
h.enqueueClosePacket(closePacket{payload: connClosePacket, addr: addr, info: info})
|
||||
},
|
||||
pers,
|
||||
|
|
377
vendor/github.com/quic-go/quic-go/packet_packer.go
generated
vendored
377
vendor/github.com/quic-go/quic-go/packet_packer.go
generated
vendored
|
@ -3,30 +3,25 @@ package quic
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/ackhandler"
|
||||
"github.com/quic-go/quic-go/internal/handshake"
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/qerr"
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
"github.com/quic-go/quic-go/internal/wire"
|
||||
)
|
||||
|
||||
var errNothingToPack = errors.New("nothing to pack")
|
||||
|
||||
type packer interface {
|
||||
PackCoalescedPacket(onlyAck bool, v protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackPacket(onlyAck bool, now time.Time, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
|
||||
MaybePackProbePacket(protocol.EncryptionLevel, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackConnectionClose(*qerr.TransportError, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackApplicationClose(*qerr.ApplicationError, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
|
||||
AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error)
|
||||
MaybePackProbePacket(protocol.EncryptionLevel, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackConnectionClose(*qerr.TransportError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackApplicationClose(*qerr.ApplicationError, protocol.ByteCount, protocol.VersionNumber) (*coalescedPacket, error)
|
||||
PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
|
||||
|
||||
SetMaxPacketSize(protocol.ByteCount)
|
||||
PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, now time.Time, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error)
|
||||
|
||||
HandleTransportParameters(*wire.TransportParameters)
|
||||
SetToken([]byte)
|
||||
}
|
||||
|
||||
|
@ -35,26 +30,31 @@ type sealer interface {
|
|||
}
|
||||
|
||||
type payload struct {
|
||||
frames []*ackhandler.Frame
|
||||
ack *wire.AckFrame
|
||||
length protocol.ByteCount
|
||||
streamFrames []ackhandler.StreamFrame
|
||||
frames []ackhandler.Frame
|
||||
ack *wire.AckFrame
|
||||
length protocol.ByteCount
|
||||
}
|
||||
|
||||
type longHeaderPacket struct {
|
||||
header *wire.ExtendedHeader
|
||||
ack *wire.AckFrame
|
||||
frames []*ackhandler.Frame
|
||||
header *wire.ExtendedHeader
|
||||
ack *wire.AckFrame
|
||||
frames []ackhandler.Frame
|
||||
streamFrames []ackhandler.StreamFrame // only used for 0-RTT packets
|
||||
|
||||
length protocol.ByteCount
|
||||
|
||||
isMTUProbePacket bool
|
||||
}
|
||||
|
||||
type shortHeaderPacket struct {
|
||||
*ackhandler.Packet
|
||||
PacketNumber protocol.PacketNumber
|
||||
Frames []ackhandler.Frame
|
||||
StreamFrames []ackhandler.StreamFrame
|
||||
Ack *wire.AckFrame
|
||||
Length protocol.ByteCount
|
||||
IsPathMTUProbePacket bool
|
||||
|
||||
// used for logging
|
||||
DestConnID protocol.ConnectionID
|
||||
Ack *wire.AckFrame
|
||||
PacketNumberLen protocol.PacketNumberLen
|
||||
KeyPhase protocol.KeyPhaseBit
|
||||
}
|
||||
|
@ -83,52 +83,6 @@ func (p *longHeaderPacket) EncryptionLevel() protocol.EncryptionLevel {
|
|||
|
||||
func (p *longHeaderPacket) IsAckEliciting() bool { return ackhandler.HasAckElicitingFrames(p.frames) }
|
||||
|
||||
func (p *longHeaderPacket) ToAckHandlerPacket(now time.Time, q *retransmissionQueue) *ackhandler.Packet {
|
||||
largestAcked := protocol.InvalidPacketNumber
|
||||
if p.ack != nil {
|
||||
largestAcked = p.ack.LargestAcked()
|
||||
}
|
||||
encLevel := p.EncryptionLevel()
|
||||
for i := range p.frames {
|
||||
if p.frames[i].OnLost != nil {
|
||||
continue
|
||||
}
|
||||
//nolint:exhaustive // Short header packets are handled separately.
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
p.frames[i].OnLost = q.AddInitial
|
||||
case protocol.EncryptionHandshake:
|
||||
p.frames[i].OnLost = q.AddHandshake
|
||||
case protocol.Encryption0RTT:
|
||||
p.frames[i].OnLost = q.AddAppData
|
||||
}
|
||||
}
|
||||
|
||||
ap := ackhandler.GetPacket()
|
||||
ap.PacketNumber = p.header.PacketNumber
|
||||
ap.LargestAcked = largestAcked
|
||||
ap.Frames = p.frames
|
||||
ap.Length = p.length
|
||||
ap.EncryptionLevel = encLevel
|
||||
ap.SendTime = now
|
||||
ap.IsPathMTUProbePacket = p.isMTUProbePacket
|
||||
return ap
|
||||
}
|
||||
|
||||
func getMaxPacketSize(addr net.Addr) protocol.ByteCount {
|
||||
maxSize := protocol.ByteCount(protocol.MinInitialPacketSize)
|
||||
// If this is not a UDP address, we don't know anything about the MTU.
|
||||
// Use the minimum size of an Initial packet as the max packet size.
|
||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
if utils.IsIPv4(udpAddr.IP) {
|
||||
maxSize = protocol.InitialPacketSizeIPv4
|
||||
} else {
|
||||
maxSize = protocol.InitialPacketSizeIPv6
|
||||
}
|
||||
}
|
||||
return maxSize
|
||||
}
|
||||
|
||||
type packetNumberManager interface {
|
||||
PeekPacketNumber(protocol.EncryptionLevel) (protocol.PacketNumber, protocol.PacketNumberLen)
|
||||
PopPacketNumber(protocol.EncryptionLevel) protocol.PacketNumber
|
||||
|
@ -143,8 +97,8 @@ type sealingManager interface {
|
|||
|
||||
type frameSource interface {
|
||||
HasData() bool
|
||||
AppendStreamFrames([]*ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount)
|
||||
AppendControlFrames([]*ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]*ackhandler.Frame, protocol.ByteCount)
|
||||
AppendStreamFrames([]ackhandler.StreamFrame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.StreamFrame, protocol.ByteCount)
|
||||
AppendControlFrames([]ackhandler.Frame, protocol.ByteCount, protocol.VersionNumber) ([]ackhandler.Frame, protocol.ByteCount)
|
||||
}
|
||||
|
||||
type ackFrameSource interface {
|
||||
|
@ -169,13 +123,23 @@ type packetPacker struct {
|
|||
datagramQueue *datagramQueue
|
||||
retransmissionQueue *retransmissionQueue
|
||||
|
||||
maxPacketSize protocol.ByteCount
|
||||
numNonAckElicitingAcks int
|
||||
}
|
||||
|
||||
var _ packer = &packetPacker{}
|
||||
|
||||
func newPacketPacker(srcConnID protocol.ConnectionID, getDestConnID func() protocol.ConnectionID, initialStream cryptoStream, handshakeStream cryptoStream, packetNumberManager packetNumberManager, retransmissionQueue *retransmissionQueue, remoteAddr net.Addr, cryptoSetup sealingManager, framer frameSource, acks ackFrameSource, datagramQueue *datagramQueue, perspective protocol.Perspective) *packetPacker {
|
||||
func newPacketPacker(
|
||||
srcConnID protocol.ConnectionID,
|
||||
getDestConnID func() protocol.ConnectionID,
|
||||
initialStream, handshakeStream cryptoStream,
|
||||
packetNumberManager packetNumberManager,
|
||||
retransmissionQueue *retransmissionQueue,
|
||||
cryptoSetup sealingManager,
|
||||
framer frameSource,
|
||||
acks ackFrameSource,
|
||||
datagramQueue *datagramQueue,
|
||||
perspective protocol.Perspective,
|
||||
) *packetPacker {
|
||||
return &packetPacker{
|
||||
cryptoSetup: cryptoSetup,
|
||||
getDestConnID: getDestConnID,
|
||||
|
@ -188,23 +152,22 @@ func newPacketPacker(srcConnID protocol.ConnectionID, getDestConnID func() proto
|
|||
framer: framer,
|
||||
acks: acks,
|
||||
pnManager: packetNumberManager,
|
||||
maxPacketSize: getMaxPacketSize(remoteAddr),
|
||||
}
|
||||
}
|
||||
|
||||
// PackConnectionClose packs a packet that closes the connection with a transport error.
|
||||
func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
func (p *packetPacker) PackConnectionClose(e *qerr.TransportError, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
var reason string
|
||||
// don't send details of crypto errors
|
||||
if !e.ErrorCode.IsCryptoError() {
|
||||
reason = e.ErrorMessage
|
||||
}
|
||||
return p.packConnectionClose(false, uint64(e.ErrorCode), e.FrameType, reason, v)
|
||||
return p.packConnectionClose(false, uint64(e.ErrorCode), e.FrameType, reason, maxPacketSize, v)
|
||||
}
|
||||
|
||||
// PackApplicationClose packs a packet that closes the connection with an application error.
|
||||
func (p *packetPacker) PackApplicationClose(e *qerr.ApplicationError, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
return p.packConnectionClose(true, uint64(e.ErrorCode), 0, e.ErrorMessage, v)
|
||||
func (p *packetPacker) PackApplicationClose(e *qerr.ApplicationError, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
return p.packConnectionClose(true, uint64(e.ErrorCode), 0, e.ErrorMessage, maxPacketSize, v)
|
||||
}
|
||||
|
||||
func (p *packetPacker) packConnectionClose(
|
||||
|
@ -212,6 +175,7 @@ func (p *packetPacker) packConnectionClose(
|
|||
errorCode uint64,
|
||||
frameType uint64,
|
||||
reason string,
|
||||
maxPacketSize protocol.ByteCount,
|
||||
v protocol.VersionNumber,
|
||||
) (*coalescedPacket, error) {
|
||||
var sealers [4]sealer
|
||||
|
@ -241,7 +205,7 @@ func (p *packetPacker) packConnectionClose(
|
|||
ccf.ReasonPhrase = ""
|
||||
}
|
||||
pl := payload{
|
||||
frames: []*ackhandler.Frame{{Frame: ccf}},
|
||||
frames: []ackhandler.Frame{{Frame: ccf}},
|
||||
length: ccf.Length(v),
|
||||
}
|
||||
|
||||
|
@ -293,20 +257,14 @@ func (p *packetPacker) packConnectionClose(
|
|||
}
|
||||
var paddingLen protocol.ByteCount
|
||||
if encLevel == protocol.EncryptionInitial {
|
||||
paddingLen = p.initialPaddingLen(payloads[i].frames, size)
|
||||
paddingLen = p.initialPaddingLen(payloads[i].frames, size, maxPacketSize)
|
||||
}
|
||||
if encLevel == protocol.Encryption1RTT {
|
||||
ap, ack, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, keyPhase, payloads[i], paddingLen, sealers[i], false, v)
|
||||
shp, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, keyPhase, payloads[i], paddingLen, maxPacketSize, sealers[i], false, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet.shortHdrPacket = &shortHeaderPacket{
|
||||
Packet: ap,
|
||||
DestConnID: connID,
|
||||
Ack: ack,
|
||||
PacketNumberLen: oneRTTPacketNumberLen,
|
||||
KeyPhase: keyPhase,
|
||||
}
|
||||
packet.shortHdrPacket = &shp
|
||||
} else {
|
||||
longHdrPacket, err := p.appendLongHeaderPacket(buffer, hdrs[i], payloads[i], paddingLen, encLevel, sealers[i], v)
|
||||
if err != nil {
|
||||
|
@ -342,25 +300,21 @@ func (p *packetPacker) shortHeaderPacketLength(connID protocol.ConnectionID, pnL
|
|||
}
|
||||
|
||||
// size is the expected size of the packet, if no padding was applied.
|
||||
func (p *packetPacker) initialPaddingLen(frames []*ackhandler.Frame, size protocol.ByteCount) protocol.ByteCount {
|
||||
func (p *packetPacker) initialPaddingLen(frames []ackhandler.Frame, currentSize, maxPacketSize protocol.ByteCount) protocol.ByteCount {
|
||||
// For the server, only ack-eliciting Initial packets need to be padded.
|
||||
if p.perspective == protocol.PerspectiveServer && !ackhandler.HasAckElicitingFrames(frames) {
|
||||
return 0
|
||||
}
|
||||
if size >= p.maxPacketSize {
|
||||
if currentSize >= maxPacketSize {
|
||||
return 0
|
||||
}
|
||||
return p.maxPacketSize - size
|
||||
return maxPacketSize - currentSize
|
||||
}
|
||||
|
||||
// PackCoalescedPacket packs a new packet.
|
||||
// It packs an Initial / Handshake if there is data to send in these packet number spaces.
|
||||
// It should only be called before the handshake is confirmed.
|
||||
func (p *packetPacker) PackCoalescedPacket(onlyAck bool, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
maxPacketSize := p.maxPacketSize
|
||||
if p.perspective == protocol.PerspectiveClient {
|
||||
maxPacketSize = protocol.MinInitialPacketSize
|
||||
}
|
||||
func (p *packetPacker) PackCoalescedPacket(onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
var (
|
||||
initialHdr, handshakeHdr, zeroRTTHdr *wire.ExtendedHeader
|
||||
initialPayload, handshakePayload, zeroRTTPayload, oneRTTPayload payload
|
||||
|
@ -442,7 +396,7 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, v protocol.VersionNumbe
|
|||
longHdrPackets: make([]*longHeaderPacket, 0, 3),
|
||||
}
|
||||
if initialPayload.length > 0 {
|
||||
padding := p.initialPaddingLen(initialPayload.frames, size)
|
||||
padding := p.initialPaddingLen(initialPayload.frames, size, maxPacketSize)
|
||||
cont, err := p.appendLongHeaderPacket(buffer, initialHdr, initialPayload, padding, protocol.EncryptionInitial, initialSealer, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -463,48 +417,44 @@ func (p *packetPacker) PackCoalescedPacket(onlyAck bool, v protocol.VersionNumbe
|
|||
}
|
||||
packet.longHdrPackets = append(packet.longHdrPackets, longHdrPacket)
|
||||
} else if oneRTTPayload.length > 0 {
|
||||
ap, ack, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, kp, oneRTTPayload, 0, oneRTTSealer, false, v)
|
||||
shp, err := p.appendShortHeaderPacket(buffer, connID, oneRTTPacketNumber, oneRTTPacketNumberLen, kp, oneRTTPayload, 0, maxPacketSize, oneRTTSealer, false, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet.shortHdrPacket = &shortHeaderPacket{
|
||||
Packet: ap,
|
||||
DestConnID: connID,
|
||||
Ack: ack,
|
||||
PacketNumberLen: oneRTTPacketNumberLen,
|
||||
KeyPhase: kp,
|
||||
}
|
||||
packet.shortHdrPacket = &shp
|
||||
}
|
||||
return packet, nil
|
||||
}
|
||||
|
||||
// PackPacket packs a packet in the application data packet number space.
|
||||
// PackAckOnlyPacket packs a packet containing only an ACK in the application data packet number space.
|
||||
// It should be called after the handshake is confirmed.
|
||||
func (p *packetPacker) PackPacket(onlyAck bool, now time.Time, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
|
||||
func (p *packetPacker) PackAckOnlyPacket(maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
|
||||
buf := getPacketBuffer()
|
||||
packet, err := p.appendPacket(buf, true, maxPacketSize, v)
|
||||
return packet, buf, err
|
||||
}
|
||||
|
||||
// AppendPacket packs a packet in the application data packet number space.
|
||||
// It should be called after the handshake is confirmed.
|
||||
func (p *packetPacker) AppendPacket(buf *packetBuffer, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error) {
|
||||
return p.appendPacket(buf, false, maxPacketSize, v)
|
||||
}
|
||||
|
||||
func (p *packetPacker) appendPacket(buf *packetBuffer, onlyAck bool, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, error) {
|
||||
sealer, err := p.cryptoSetup.Get1RTTSealer()
|
||||
if err != nil {
|
||||
return shortHeaderPacket{}, nil, err
|
||||
return shortHeaderPacket{}, err
|
||||
}
|
||||
pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT)
|
||||
connID := p.getDestConnID()
|
||||
hdrLen := wire.ShortHeaderLen(connID, pnLen)
|
||||
pl := p.maybeGetShortHeaderPacket(sealer, hdrLen, p.maxPacketSize, onlyAck, true, v)
|
||||
pl := p.maybeGetShortHeaderPacket(sealer, hdrLen, maxPacketSize, onlyAck, true, v)
|
||||
if pl.length == 0 {
|
||||
return shortHeaderPacket{}, nil, errNothingToPack
|
||||
return shortHeaderPacket{}, errNothingToPack
|
||||
}
|
||||
kp := sealer.KeyPhase()
|
||||
buffer := getPacketBuffer()
|
||||
ap, ack, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, 0, sealer, false, v)
|
||||
if err != nil {
|
||||
return shortHeaderPacket{}, nil, err
|
||||
}
|
||||
return shortHeaderPacket{
|
||||
Packet: ap,
|
||||
DestConnID: connID,
|
||||
Ack: ack,
|
||||
PacketNumberLen: pnLen,
|
||||
KeyPhase: kp,
|
||||
}, buffer, nil
|
||||
|
||||
return p.appendShortHeaderPacket(buf, connID, pn, pnLen, kp, pl, 0, maxPacketSize, sealer, false, v)
|
||||
}
|
||||
|
||||
func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, encLevel protocol.EncryptionLevel, onlyAck, ackAllowed bool, v protocol.VersionNumber) (*wire.ExtendedHeader, payload) {
|
||||
|
@ -519,14 +469,17 @@ func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, en
|
|||
}
|
||||
|
||||
var s cryptoStream
|
||||
var handler ackhandler.FrameHandler
|
||||
var hasRetransmission bool
|
||||
//nolint:exhaustive // Initial and Handshake are the only two encryption levels here.
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
s = p.initialStream
|
||||
handler = p.retransmissionQueue.InitialAckHandler()
|
||||
hasRetransmission = p.retransmissionQueue.HasInitialData()
|
||||
case protocol.EncryptionHandshake:
|
||||
s = p.handshakeStream
|
||||
handler = p.retransmissionQueue.HandshakeAckHandler()
|
||||
hasRetransmission = p.retransmissionQueue.HasHandshakeData()
|
||||
}
|
||||
|
||||
|
@ -550,27 +503,27 @@ func (p *packetPacker) maybeGetCryptoPacket(maxPacketSize protocol.ByteCount, en
|
|||
maxPacketSize -= hdr.GetLength(v)
|
||||
if hasRetransmission {
|
||||
for {
|
||||
var f wire.Frame
|
||||
var f ackhandler.Frame
|
||||
//nolint:exhaustive // 0-RTT packets can't contain any retransmission.s
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
f = p.retransmissionQueue.GetInitialFrame(maxPacketSize, v)
|
||||
f.Frame = p.retransmissionQueue.GetInitialFrame(maxPacketSize, v)
|
||||
f.Handler = p.retransmissionQueue.InitialAckHandler()
|
||||
case protocol.EncryptionHandshake:
|
||||
f = p.retransmissionQueue.GetHandshakeFrame(maxPacketSize, v)
|
||||
f.Frame = p.retransmissionQueue.GetHandshakeFrame(maxPacketSize, v)
|
||||
f.Handler = p.retransmissionQueue.HandshakeAckHandler()
|
||||
}
|
||||
if f == nil {
|
||||
if f.Frame == nil {
|
||||
break
|
||||
}
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = f
|
||||
pl.frames = append(pl.frames, af)
|
||||
frameLen := f.Length(v)
|
||||
pl.frames = append(pl.frames, f)
|
||||
frameLen := f.Frame.Length(v)
|
||||
pl.length += frameLen
|
||||
maxPacketSize -= frameLen
|
||||
}
|
||||
} else if s.HasData() {
|
||||
cf := s.PopCryptoFrame(maxPacketSize)
|
||||
pl.frames = []*ackhandler.Frame{{Frame: cf}}
|
||||
pl.frames = []ackhandler.Frame{{Frame: cf, Handler: handler}}
|
||||
pl.length += cf.Length(v)
|
||||
}
|
||||
return hdr, pl
|
||||
|
@ -595,18 +548,14 @@ func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount,
|
|||
pl := p.composeNextPacket(maxPayloadSize, onlyAck, ackAllowed, v)
|
||||
|
||||
// check if we have anything to send
|
||||
if len(pl.frames) == 0 {
|
||||
if len(pl.frames) == 0 && len(pl.streamFrames) == 0 {
|
||||
if pl.ack == nil {
|
||||
return payload{}
|
||||
}
|
||||
// the packet only contains an ACK
|
||||
if p.numNonAckElicitingAcks >= protocol.MaxNonAckElicitingAcks {
|
||||
ping := &wire.PingFrame{}
|
||||
// don't retransmit the PING frame when it is lost
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = ping
|
||||
af.OnLost = func(wire.Frame) {}
|
||||
pl.frames = append(pl.frames, af)
|
||||
pl.frames = append(pl.frames, ackhandler.Frame{Frame: ping})
|
||||
pl.length += ping.Length(v)
|
||||
p.numNonAckElicitingAcks = 0
|
||||
} else {
|
||||
|
@ -621,15 +570,12 @@ func (p *packetPacker) maybeGetAppDataPacket(maxPayloadSize protocol.ByteCount,
|
|||
func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAck, ackAllowed bool, v protocol.VersionNumber) payload {
|
||||
if onlyAck {
|
||||
if ack := p.acks.GetAckFrame(protocol.Encryption1RTT, true); ack != nil {
|
||||
return payload{
|
||||
ack: ack,
|
||||
length: ack.Length(v),
|
||||
}
|
||||
return payload{ack: ack, length: ack.Length(v)}
|
||||
}
|
||||
return payload{}
|
||||
}
|
||||
|
||||
pl := payload{frames: make([]*ackhandler.Frame, 0, 1)}
|
||||
pl := payload{streamFrames: make([]ackhandler.StreamFrame, 0, 1)}
|
||||
|
||||
hasData := p.framer.HasData()
|
||||
hasRetransmission := p.retransmissionQueue.HasAppData()
|
||||
|
@ -647,11 +593,7 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAc
|
|||
if f := p.datagramQueue.Peek(); f != nil {
|
||||
size := f.Length(v)
|
||||
if size <= maxFrameSize-pl.length {
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = f
|
||||
// set it to a no-op. Then we won't set the default callback, which would retransmit the frame.
|
||||
af.OnLost = func(wire.Frame) {}
|
||||
pl.frames = append(pl.frames, af)
|
||||
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f})
|
||||
pl.length += size
|
||||
p.datagramQueue.Pop()
|
||||
}
|
||||
|
@ -672,25 +614,28 @@ func (p *packetPacker) composeNextPacket(maxFrameSize protocol.ByteCount, onlyAc
|
|||
if f == nil {
|
||||
break
|
||||
}
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = f
|
||||
pl.frames = append(pl.frames, af)
|
||||
pl.frames = append(pl.frames, ackhandler.Frame{Frame: f, Handler: p.retransmissionQueue.AppDataAckHandler()})
|
||||
pl.length += f.Length(v)
|
||||
}
|
||||
}
|
||||
|
||||
if hasData {
|
||||
var lengthAdded protocol.ByteCount
|
||||
startLen := len(pl.frames)
|
||||
pl.frames, lengthAdded = p.framer.AppendControlFrames(pl.frames, maxFrameSize-pl.length, v)
|
||||
pl.length += lengthAdded
|
||||
// add handlers for the control frames that were added
|
||||
for i := startLen; i < len(pl.frames); i++ {
|
||||
pl.frames[i].Handler = p.retransmissionQueue.AppDataAckHandler()
|
||||
}
|
||||
|
||||
pl.frames, lengthAdded = p.framer.AppendStreamFrames(pl.frames, maxFrameSize-pl.length, v)
|
||||
pl.streamFrames, lengthAdded = p.framer.AppendStreamFrames(pl.streamFrames, maxFrameSize-pl.length, v)
|
||||
pl.length += lengthAdded
|
||||
}
|
||||
return pl
|
||||
}
|
||||
|
||||
func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, maxPacketSize protocol.ByteCount, v protocol.VersionNumber) (*coalescedPacket, error) {
|
||||
if encLevel == protocol.Encryption1RTT {
|
||||
s, err := p.cryptoSetup.Get1RTTSealer()
|
||||
if err != nil {
|
||||
|
@ -700,23 +645,17 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, v
|
|||
connID := p.getDestConnID()
|
||||
pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT)
|
||||
hdrLen := wire.ShortHeaderLen(connID, pnLen)
|
||||
pl := p.maybeGetAppDataPacket(p.maxPacketSize-protocol.ByteCount(s.Overhead())-hdrLen, false, true, v)
|
||||
pl := p.maybeGetAppDataPacket(maxPacketSize-protocol.ByteCount(s.Overhead())-hdrLen, false, true, v)
|
||||
if pl.length == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
buffer := getPacketBuffer()
|
||||
packet := &coalescedPacket{buffer: buffer}
|
||||
ap, ack, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, 0, s, false, v)
|
||||
shp, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, 0, maxPacketSize, s, false, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packet.shortHdrPacket = &shortHeaderPacket{
|
||||
Packet: ap,
|
||||
DestConnID: connID,
|
||||
Ack: ack,
|
||||
PacketNumberLen: pnLen,
|
||||
KeyPhase: kp,
|
||||
}
|
||||
packet.shortHdrPacket = &shp
|
||||
return packet, nil
|
||||
}
|
||||
|
||||
|
@ -731,14 +670,14 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, v
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr, pl = p.maybeGetCryptoPacket(p.maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionInitial, false, true, v)
|
||||
hdr, pl = p.maybeGetCryptoPacket(maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionInitial, false, true, v)
|
||||
case protocol.EncryptionHandshake:
|
||||
var err error
|
||||
sealer, err = p.cryptoSetup.GetHandshakeSealer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hdr, pl = p.maybeGetCryptoPacket(p.maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionHandshake, false, true, v)
|
||||
hdr, pl = p.maybeGetCryptoPacket(maxPacketSize-protocol.ByteCount(sealer.Overhead()), protocol.EncryptionHandshake, false, true, v)
|
||||
default:
|
||||
panic("unknown encryption level")
|
||||
}
|
||||
|
@ -751,7 +690,7 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, v
|
|||
size := p.longHeaderPacketLength(hdr, pl, v) + protocol.ByteCount(sealer.Overhead())
|
||||
var padding protocol.ByteCount
|
||||
if encLevel == protocol.EncryptionInitial {
|
||||
padding = p.initialPaddingLen(pl.frames, size)
|
||||
padding = p.initialPaddingLen(pl.frames, size, maxPacketSize)
|
||||
}
|
||||
|
||||
longHdrPacket, err := p.appendLongHeaderPacket(buffer, hdr, pl, padding, encLevel, sealer, v)
|
||||
|
@ -762,10 +701,10 @@ func (p *packetPacker) MaybePackProbePacket(encLevel protocol.EncryptionLevel, v
|
|||
return packet, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, now time.Time, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
|
||||
func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.ByteCount, v protocol.VersionNumber) (shortHeaderPacket, *packetBuffer, error) {
|
||||
pl := payload{
|
||||
frames: []*ackhandler.Frame{&ping},
|
||||
length: ping.Length(v),
|
||||
frames: []ackhandler.Frame{ping},
|
||||
length: ping.Frame.Length(v),
|
||||
}
|
||||
buffer := getPacketBuffer()
|
||||
s, err := p.cryptoSetup.Get1RTTSealer()
|
||||
|
@ -776,17 +715,8 @@ func (p *packetPacker) PackMTUProbePacket(ping ackhandler.Frame, size protocol.B
|
|||
pn, pnLen := p.pnManager.PeekPacketNumber(protocol.Encryption1RTT)
|
||||
padding := size - p.shortHeaderPacketLength(connID, pnLen, pl) - protocol.ByteCount(s.Overhead())
|
||||
kp := s.KeyPhase()
|
||||
ap, ack, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, padding, s, true, v)
|
||||
if err != nil {
|
||||
return shortHeaderPacket{}, nil, err
|
||||
}
|
||||
return shortHeaderPacket{
|
||||
Packet: ap,
|
||||
DestConnID: connID,
|
||||
Ack: ack,
|
||||
PacketNumberLen: pnLen,
|
||||
KeyPhase: kp,
|
||||
}, buffer, nil
|
||||
packet, err := p.appendShortHeaderPacket(buffer, connID, pn, pnLen, kp, pl, padding, size, s, true, v)
|
||||
return packet, buffer, err
|
||||
}
|
||||
|
||||
func (p *packetPacker) getLongHeader(encLevel protocol.EncryptionLevel, v protocol.VersionNumber) *wire.ExtendedHeader {
|
||||
|
@ -829,23 +759,22 @@ func (p *packetPacker) appendLongHeaderPacket(buffer *packetBuffer, header *wire
|
|||
}
|
||||
payloadOffset := protocol.ByteCount(len(raw))
|
||||
|
||||
pn := p.pnManager.PopPacketNumber(encLevel)
|
||||
if pn != header.PacketNumber {
|
||||
return nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
|
||||
}
|
||||
|
||||
raw, err = p.appendPacketPayload(raw, pl, paddingLen, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
raw = p.encryptPacket(raw, sealer, pn, payloadOffset, pnLen)
|
||||
raw = p.encryptPacket(raw, sealer, header.PacketNumber, payloadOffset, pnLen)
|
||||
buffer.Data = buffer.Data[:len(buffer.Data)+len(raw)]
|
||||
|
||||
if pn := p.pnManager.PopPacketNumber(encLevel); pn != header.PacketNumber {
|
||||
return nil, fmt.Errorf("packetPacker BUG: Peeked and Popped packet numbers do not match: expected %d, got %d", pn, header.PacketNumber)
|
||||
}
|
||||
return &longHeaderPacket{
|
||||
header: header,
|
||||
ack: pl.ack,
|
||||
frames: pl.frames,
|
||||
length: protocol.ByteCount(len(raw)),
|
||||
header: header,
|
||||
ack: pl.ack,
|
||||
frames: pl.frames,
|
||||
streamFrames: pl.streamFrames,
|
||||
length: protocol.ByteCount(len(raw)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -856,11 +785,11 @@ func (p *packetPacker) appendShortHeaderPacket(
|
|||
pnLen protocol.PacketNumberLen,
|
||||
kp protocol.KeyPhaseBit,
|
||||
pl payload,
|
||||
padding protocol.ByteCount,
|
||||
padding, maxPacketSize protocol.ByteCount,
|
||||
sealer sealer,
|
||||
isMTUProbePacket bool,
|
||||
v protocol.VersionNumber,
|
||||
) (*ackhandler.Packet, *wire.AckFrame, error) {
|
||||
) (shortHeaderPacket, error) {
|
||||
var paddingLen protocol.ByteCount
|
||||
if pl.length < 4-protocol.ByteCount(pnLen) {
|
||||
paddingLen = 4 - protocol.ByteCount(pnLen) - pl.length
|
||||
|
@ -871,48 +800,36 @@ func (p *packetPacker) appendShortHeaderPacket(
|
|||
raw := buffer.Data[startLen:]
|
||||
raw, err := wire.AppendShortHeader(raw, connID, pn, pnLen, kp)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return shortHeaderPacket{}, err
|
||||
}
|
||||
payloadOffset := protocol.ByteCount(len(raw))
|
||||
|
||||
if pn != p.pnManager.PopPacketNumber(protocol.Encryption1RTT) {
|
||||
return nil, nil, errors.New("packetPacker BUG: Peeked and Popped packet numbers do not match")
|
||||
}
|
||||
|
||||
raw, err = p.appendPacketPayload(raw, pl, paddingLen, v)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return shortHeaderPacket{}, err
|
||||
}
|
||||
if !isMTUProbePacket {
|
||||
if size := protocol.ByteCount(len(raw) + sealer.Overhead()); size > p.maxPacketSize {
|
||||
return nil, nil, fmt.Errorf("PacketPacker BUG: packet too large (%d bytes, allowed %d bytes)", size, p.maxPacketSize)
|
||||
if size := protocol.ByteCount(len(raw) + sealer.Overhead()); size > maxPacketSize {
|
||||
return shortHeaderPacket{}, fmt.Errorf("PacketPacker BUG: packet too large (%d bytes, allowed %d bytes)", size, maxPacketSize)
|
||||
}
|
||||
}
|
||||
raw = p.encryptPacket(raw, sealer, pn, payloadOffset, protocol.ByteCount(pnLen))
|
||||
buffer.Data = buffer.Data[:len(buffer.Data)+len(raw)]
|
||||
|
||||
// create the ackhandler.Packet
|
||||
largestAcked := protocol.InvalidPacketNumber
|
||||
if pl.ack != nil {
|
||||
largestAcked = pl.ack.LargestAcked()
|
||||
if newPN := p.pnManager.PopPacketNumber(protocol.Encryption1RTT); newPN != pn {
|
||||
return shortHeaderPacket{}, fmt.Errorf("packetPacker BUG: Peeked and Popped packet numbers do not match: expected %d, got %d", pn, newPN)
|
||||
}
|
||||
for i := range pl.frames {
|
||||
if pl.frames[i].OnLost != nil {
|
||||
continue
|
||||
}
|
||||
pl.frames[i].OnLost = p.retransmissionQueue.AddAppData
|
||||
}
|
||||
|
||||
ap := ackhandler.GetPacket()
|
||||
ap.PacketNumber = pn
|
||||
ap.LargestAcked = largestAcked
|
||||
ap.Frames = pl.frames
|
||||
ap.Length = protocol.ByteCount(len(raw))
|
||||
ap.EncryptionLevel = protocol.Encryption1RTT
|
||||
ap.SendTime = time.Now()
|
||||
ap.IsPathMTUProbePacket = isMTUProbePacket
|
||||
|
||||
return ap, pl.ack, nil
|
||||
return shortHeaderPacket{
|
||||
PacketNumber: pn,
|
||||
PacketNumberLen: pnLen,
|
||||
KeyPhase: kp,
|
||||
StreamFrames: pl.streamFrames,
|
||||
Frames: pl.frames,
|
||||
Ack: pl.ack,
|
||||
Length: protocol.ByteCount(len(raw)),
|
||||
DestConnID: connID,
|
||||
IsPathMTUProbePacket: isMTUProbePacket,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen protocol.ByteCount, v protocol.VersionNumber) ([]byte, error) {
|
||||
|
@ -927,9 +844,16 @@ func (p *packetPacker) appendPacketPayload(raw []byte, pl payload, paddingLen pr
|
|||
if paddingLen > 0 {
|
||||
raw = append(raw, make([]byte, paddingLen)...)
|
||||
}
|
||||
for _, frame := range pl.frames {
|
||||
for _, f := range pl.frames {
|
||||
var err error
|
||||
raw, err = frame.Append(raw, v)
|
||||
raw, err = f.Frame.Append(raw, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, f := range pl.streamFrames {
|
||||
var err error
|
||||
raw, err = f.Frame.Append(raw, v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -953,16 +877,3 @@ func (p *packetPacker) encryptPacket(raw []byte, sealer sealer, pn protocol.Pack
|
|||
func (p *packetPacker) SetToken(token []byte) {
|
||||
p.token = token
|
||||
}
|
||||
|
||||
// When a higher MTU is discovered, use it.
|
||||
func (p *packetPacker) SetMaxPacketSize(s protocol.ByteCount) {
|
||||
p.maxPacketSize = s
|
||||
}
|
||||
|
||||
// If the peer sets a max_packet_size that's smaller than the size we're currently using,
|
||||
// we need to reduce the size of packets we send.
|
||||
func (p *packetPacker) HandleTransportParameters(params *wire.TransportParameters) {
|
||||
if params.MaxUDPPayloadSize != 0 {
|
||||
p.maxPacketSize = utils.Min(p.maxPacketSize, params.MaxUDPPayloadSize)
|
||||
}
|
||||
}
|
||||
|
|
4
vendor/github.com/quic-go/quic-go/receive_stream.go
generated
vendored
4
vendor/github.com/quic-go/quic-go/receive_stream.go
generated
vendored
|
@ -179,6 +179,10 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
|
|||
|
||||
if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast {
|
||||
s.finRead = true
|
||||
s.currentFrame = nil
|
||||
if s.currentFrameDone != nil {
|
||||
s.currentFrameDone()
|
||||
}
|
||||
return true, bytesRead, io.EOF
|
||||
}
|
||||
}
|
||||
|
|
57
vendor/github.com/quic-go/quic-go/retransmission_queue.go
generated
vendored
57
vendor/github.com/quic-go/quic-go/retransmission_queue.go
generated
vendored
|
@ -3,6 +3,8 @@ package quic
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/ackhandler"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
"github.com/quic-go/quic-go/internal/wire"
|
||||
)
|
||||
|
@ -21,7 +23,23 @@ func newRetransmissionQueue() *retransmissionQueue {
|
|||
return &retransmissionQueue{}
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) AddInitial(f wire.Frame) {
|
||||
// AddPing queues a ping.
|
||||
// It is used when a probe packet needs to be sent
|
||||
func (q *retransmissionQueue) AddPing(encLevel protocol.EncryptionLevel) {
|
||||
//nolint:exhaustive // Cannot send probe packets for 0-RTT.
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
q.addInitial(&wire.PingFrame{})
|
||||
case protocol.EncryptionHandshake:
|
||||
q.addHandshake(&wire.PingFrame{})
|
||||
case protocol.Encryption1RTT:
|
||||
q.addAppData(&wire.PingFrame{})
|
||||
default:
|
||||
panic("unexpected encryption level")
|
||||
}
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) addInitial(f wire.Frame) {
|
||||
if cf, ok := f.(*wire.CryptoFrame); ok {
|
||||
q.initialCryptoData = append(q.initialCryptoData, cf)
|
||||
return
|
||||
|
@ -29,7 +47,7 @@ func (q *retransmissionQueue) AddInitial(f wire.Frame) {
|
|||
q.initial = append(q.initial, f)
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) AddHandshake(f wire.Frame) {
|
||||
func (q *retransmissionQueue) addHandshake(f wire.Frame) {
|
||||
if cf, ok := f.(*wire.CryptoFrame); ok {
|
||||
q.handshakeCryptoData = append(q.handshakeCryptoData, cf)
|
||||
return
|
||||
|
@ -49,7 +67,7 @@ func (q *retransmissionQueue) HasAppData() bool {
|
|||
return len(q.appData) > 0
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) AddAppData(f wire.Frame) {
|
||||
func (q *retransmissionQueue) addAppData(f wire.Frame) {
|
||||
if _, ok := f.(*wire.StreamFrame); ok {
|
||||
panic("STREAM frames are handled with their respective streams.")
|
||||
}
|
||||
|
@ -127,3 +145,36 @@ func (q *retransmissionQueue) DropPackets(encLevel protocol.EncryptionLevel) {
|
|||
panic(fmt.Sprintf("unexpected encryption level: %s", encLevel))
|
||||
}
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) InitialAckHandler() ackhandler.FrameHandler {
|
||||
return (*retransmissionQueueInitialAckHandler)(q)
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) HandshakeAckHandler() ackhandler.FrameHandler {
|
||||
return (*retransmissionQueueHandshakeAckHandler)(q)
|
||||
}
|
||||
|
||||
func (q *retransmissionQueue) AppDataAckHandler() ackhandler.FrameHandler {
|
||||
return (*retransmissionQueueAppDataAckHandler)(q)
|
||||
}
|
||||
|
||||
type retransmissionQueueInitialAckHandler retransmissionQueue
|
||||
|
||||
func (q *retransmissionQueueInitialAckHandler) OnAcked(wire.Frame) {}
|
||||
func (q *retransmissionQueueInitialAckHandler) OnLost(f wire.Frame) {
|
||||
(*retransmissionQueue)(q).addInitial(f)
|
||||
}
|
||||
|
||||
type retransmissionQueueHandshakeAckHandler retransmissionQueue
|
||||
|
||||
func (q *retransmissionQueueHandshakeAckHandler) OnAcked(wire.Frame) {}
|
||||
func (q *retransmissionQueueHandshakeAckHandler) OnLost(f wire.Frame) {
|
||||
(*retransmissionQueue)(q).addHandshake(f)
|
||||
}
|
||||
|
||||
type retransmissionQueueAppDataAckHandler retransmissionQueue
|
||||
|
||||
func (q *retransmissionQueueAppDataAckHandler) OnAcked(wire.Frame) {}
|
||||
func (q *retransmissionQueueAppDataAckHandler) OnLost(f wire.Frame) {
|
||||
(*retransmissionQueue)(q).addAppData(f)
|
||||
}
|
||||
|
|
43
vendor/github.com/quic-go/quic-go/send_conn.go
generated
vendored
43
vendor/github.com/quic-go/quic-go/send_conn.go
generated
vendored
|
@ -1,38 +1,65 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
// A sendConn allows sending using a simple Write() on a non-connected packet conn.
|
||||
type sendConn interface {
|
||||
Write([]byte) error
|
||||
Write(b []byte, size protocol.ByteCount) error
|
||||
Close() error
|
||||
LocalAddr() net.Addr
|
||||
RemoteAddr() net.Addr
|
||||
|
||||
capabilities() connCapabilities
|
||||
}
|
||||
|
||||
type sconn struct {
|
||||
rawConn
|
||||
|
||||
remoteAddr net.Addr
|
||||
info *packetInfo
|
||||
info packetInfo
|
||||
oob []byte
|
||||
}
|
||||
|
||||
var _ sendConn = &sconn{}
|
||||
|
||||
func newSendConn(c rawConn, remote net.Addr, info *packetInfo) *sconn {
|
||||
func newSendConn(c rawConn, remote net.Addr) *sconn {
|
||||
sc := &sconn{
|
||||
rawConn: c,
|
||||
remoteAddr: remote,
|
||||
}
|
||||
if c.capabilities().GSO {
|
||||
// add 32 bytes, so we can add the UDP_SEGMENT msg
|
||||
sc.oob = make([]byte, 0, 32)
|
||||
}
|
||||
return sc
|
||||
}
|
||||
|
||||
func newSendConnWithPacketInfo(c rawConn, remote net.Addr, info packetInfo) *sconn {
|
||||
oob := info.OOB()
|
||||
if c.capabilities().GSO {
|
||||
// add 32 bytes, so we can add the UDP_SEGMENT msg
|
||||
l := len(oob)
|
||||
oob = append(oob, make([]byte, 32)...)
|
||||
oob = oob[:l]
|
||||
}
|
||||
return &sconn{
|
||||
rawConn: c,
|
||||
remoteAddr: remote,
|
||||
info: info,
|
||||
oob: info.OOB(),
|
||||
oob: oob,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *sconn) Write(p []byte) error {
|
||||
_, err := c.WritePacket(p, c.remoteAddr, c.oob)
|
||||
func (c *sconn) Write(p []byte, size protocol.ByteCount) error {
|
||||
if size > math.MaxUint16 {
|
||||
panic("size overflow")
|
||||
}
|
||||
_, err := c.WritePacket(p, uint16(size), c.remoteAddr, c.oob)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -42,10 +69,10 @@ func (c *sconn) RemoteAddr() net.Addr {
|
|||
|
||||
func (c *sconn) LocalAddr() net.Addr {
|
||||
addr := c.rawConn.LocalAddr()
|
||||
if c.info != nil {
|
||||
if c.info.addr.IsValid() {
|
||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
addrCopy := *udpAddr
|
||||
addrCopy.IP = c.info.addr
|
||||
addrCopy.IP = c.info.addr.AsSlice()
|
||||
addr = &addrCopy
|
||||
}
|
||||
}
|
||||
|
|
23
vendor/github.com/quic-go/quic-go/send_queue.go
generated
vendored
23
vendor/github.com/quic-go/quic-go/send_queue.go
generated
vendored
|
@ -1,15 +1,22 @@
|
|||
package quic
|
||||
|
||||
import "github.com/quic-go/quic-go/internal/protocol"
|
||||
|
||||
type sender interface {
|
||||
Send(p *packetBuffer)
|
||||
Send(p *packetBuffer, packetSize protocol.ByteCount)
|
||||
Run() error
|
||||
WouldBlock() bool
|
||||
Available() <-chan struct{}
|
||||
Close()
|
||||
}
|
||||
|
||||
type queueEntry struct {
|
||||
buf *packetBuffer
|
||||
size protocol.ByteCount
|
||||
}
|
||||
|
||||
type sendQueue struct {
|
||||
queue chan *packetBuffer
|
||||
queue chan queueEntry
|
||||
closeCalled chan struct{} // runStopped when Close() is called
|
||||
runStopped chan struct{} // runStopped when the run loop returns
|
||||
available chan struct{}
|
||||
|
@ -26,16 +33,16 @@ func newSendQueue(conn sendConn) sender {
|
|||
runStopped: make(chan struct{}),
|
||||
closeCalled: make(chan struct{}),
|
||||
available: make(chan struct{}, 1),
|
||||
queue: make(chan *packetBuffer, sendQueueCapacity),
|
||||
queue: make(chan queueEntry, sendQueueCapacity),
|
||||
}
|
||||
}
|
||||
|
||||
// Send sends out a packet. It's guaranteed to not block.
|
||||
// Callers need to make sure that there's actually space in the send queue by calling WouldBlock.
|
||||
// Otherwise Send will panic.
|
||||
func (h *sendQueue) Send(p *packetBuffer) {
|
||||
func (h *sendQueue) Send(p *packetBuffer, size protocol.ByteCount) {
|
||||
select {
|
||||
case h.queue <- p:
|
||||
case h.queue <- queueEntry{buf: p, size: size}:
|
||||
// clear available channel if we've reached capacity
|
||||
if len(h.queue) == sendQueueCapacity {
|
||||
select {
|
||||
|
@ -69,8 +76,8 @@ func (h *sendQueue) Run() error {
|
|||
h.closeCalled = nil // prevent this case from being selected again
|
||||
// make sure that all queued packets are actually sent out
|
||||
shouldClose = true
|
||||
case p := <-h.queue:
|
||||
if err := h.conn.Write(p.Data); err != nil {
|
||||
case e := <-h.queue:
|
||||
if err := h.conn.Write(e.buf.Data, e.size); err != nil {
|
||||
// This additional check enables:
|
||||
// 1. Checking for "datagram too large" message from the kernel, as such,
|
||||
// 2. Path MTU discovery,and
|
||||
|
@ -79,7 +86,7 @@ func (h *sendQueue) Run() error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
p.Release()
|
||||
e.buf.Release()
|
||||
select {
|
||||
case h.available <- struct{}{}:
|
||||
default:
|
||||
|
|
95
vendor/github.com/quic-go/quic-go/send_stream.go
generated
vendored
95
vendor/github.com/quic-go/quic-go/send_stream.go
generated
vendored
|
@ -18,7 +18,7 @@ type sendStreamI interface {
|
|||
SendStream
|
||||
handleStopSendingFrame(*wire.StopSendingFrame)
|
||||
hasData() bool
|
||||
popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*ackhandler.Frame, bool)
|
||||
popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (frame ackhandler.StreamFrame, ok, hasMore bool)
|
||||
closeForShutdown(error)
|
||||
updateSendWindow(protocol.ByteCount)
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ func (s *sendStream) canBufferStreamFrame() bool {
|
|||
|
||||
// popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream
|
||||
// maxBytes is the maximum length this frame (including frame header) will have.
|
||||
func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*ackhandler.Frame, bool /* has more data to send */) {
|
||||
func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (af ackhandler.StreamFrame, ok, hasMore bool) {
|
||||
s.mutex.Lock()
|
||||
f, hasMoreData := s.popNewOrRetransmittedStreamFrame(maxBytes, v)
|
||||
if f != nil {
|
||||
|
@ -207,13 +207,12 @@ func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount, v protocol.Vers
|
|||
s.mutex.Unlock()
|
||||
|
||||
if f == nil {
|
||||
return nil, hasMoreData
|
||||
return ackhandler.StreamFrame{}, false, hasMoreData
|
||||
}
|
||||
af := ackhandler.GetFrame()
|
||||
af.Frame = f
|
||||
af.OnLost = s.queueRetransmission
|
||||
af.OnAcked = s.frameAcked
|
||||
return af, hasMoreData
|
||||
return ackhandler.StreamFrame{
|
||||
Frame: f,
|
||||
Handler: (*sendStreamAckHandler)(s),
|
||||
}, true, hasMoreData
|
||||
}
|
||||
|
||||
func (s *sendStream) popNewOrRetransmittedStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*wire.StreamFrame, bool /* has more data to send */) {
|
||||
|
@ -348,26 +347,6 @@ func (s *sendStream) getDataForWriting(f *wire.StreamFrame, maxBytes protocol.By
|
|||
}
|
||||
}
|
||||
|
||||
func (s *sendStream) frameAcked(f wire.Frame) {
|
||||
f.(*wire.StreamFrame).PutBack()
|
||||
|
||||
s.mutex.Lock()
|
||||
if s.cancelWriteErr != nil {
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
s.numOutstandingFrames--
|
||||
if s.numOutstandingFrames < 0 {
|
||||
panic("numOutStandingFrames negative")
|
||||
}
|
||||
newlyCompleted := s.isNewlyCompleted()
|
||||
s.mutex.Unlock()
|
||||
|
||||
if newlyCompleted {
|
||||
s.sender.onStreamCompleted(s.streamID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sendStream) isNewlyCompleted() bool {
|
||||
completed := (s.finSent || s.cancelWriteErr != nil) && s.numOutstandingFrames == 0 && len(s.retransmissionQueue) == 0
|
||||
if completed && !s.completed {
|
||||
|
@ -377,24 +356,6 @@ func (s *sendStream) isNewlyCompleted() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *sendStream) queueRetransmission(f wire.Frame) {
|
||||
sf := f.(*wire.StreamFrame)
|
||||
sf.DataLenPresent = true
|
||||
s.mutex.Lock()
|
||||
if s.cancelWriteErr != nil {
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
s.retransmissionQueue = append(s.retransmissionQueue, sf)
|
||||
s.numOutstandingFrames--
|
||||
if s.numOutstandingFrames < 0 {
|
||||
panic("numOutStandingFrames negative")
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
||||
s.sender.onHasStreamData(s.streamID)
|
||||
}
|
||||
|
||||
func (s *sendStream) Close() error {
|
||||
s.mutex.Lock()
|
||||
if s.closeForShutdownErr != nil {
|
||||
|
@ -487,3 +448,45 @@ func (s *sendStream) signalWrite() {
|
|||
default:
|
||||
}
|
||||
}
|
||||
|
||||
type sendStreamAckHandler sendStream
|
||||
|
||||
var _ ackhandler.FrameHandler = &sendStreamAckHandler{}
|
||||
|
||||
func (s *sendStreamAckHandler) OnAcked(f wire.Frame) {
|
||||
sf := f.(*wire.StreamFrame)
|
||||
sf.PutBack()
|
||||
s.mutex.Lock()
|
||||
if s.cancelWriteErr != nil {
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
s.numOutstandingFrames--
|
||||
if s.numOutstandingFrames < 0 {
|
||||
panic("numOutStandingFrames negative")
|
||||
}
|
||||
newlyCompleted := (*sendStream)(s).isNewlyCompleted()
|
||||
s.mutex.Unlock()
|
||||
|
||||
if newlyCompleted {
|
||||
s.sender.onStreamCompleted(s.streamID)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sendStreamAckHandler) OnLost(f wire.Frame) {
|
||||
sf := f.(*wire.StreamFrame)
|
||||
s.mutex.Lock()
|
||||
if s.cancelWriteErr != nil {
|
||||
s.mutex.Unlock()
|
||||
return
|
||||
}
|
||||
sf.DataLenPresent = true
|
||||
s.retransmissionQueue = append(s.retransmissionQueue, sf)
|
||||
s.numOutstandingFrames--
|
||||
if s.numOutstandingFrames < 0 {
|
||||
panic("numOutStandingFrames negative")
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
||||
s.sender.onHasStreamData(s.streamID)
|
||||
}
|
||||
|
|
72
vendor/github.com/quic-go/quic-go/server.go
generated
vendored
72
vendor/github.com/quic-go/quic-go/server.go
generated
vendored
|
@ -24,7 +24,7 @@ var ErrServerClosed = errors.New("quic: server closed")
|
|||
|
||||
// packetHandler handles packets
|
||||
type packetHandler interface {
|
||||
handlePacket(*receivedPacket)
|
||||
handlePacket(receivedPacket)
|
||||
shutdown()
|
||||
destroy(error)
|
||||
getPerspective() protocol.Perspective
|
||||
|
@ -42,7 +42,7 @@ type packetHandlerManager interface {
|
|||
type quicConn interface {
|
||||
EarlyConnection
|
||||
earlyConnReady() <-chan struct{}
|
||||
handlePacket(*receivedPacket)
|
||||
handlePacket(receivedPacket)
|
||||
GetVersion() protocol.VersionNumber
|
||||
getPerspective() protocol.Perspective
|
||||
run() error
|
||||
|
@ -51,7 +51,7 @@ type quicConn interface {
|
|||
}
|
||||
|
||||
type zeroRTTQueue struct {
|
||||
packets []*receivedPacket
|
||||
packets []receivedPacket
|
||||
expiration time.Time
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ type baseServer struct {
|
|||
connHandler packetHandlerManager
|
||||
onClose func()
|
||||
|
||||
receivedPackets chan *receivedPacket
|
||||
receivedPackets chan receivedPacket
|
||||
|
||||
nextZeroRTTCleanup time.Time
|
||||
zeroRTTQueues map[protocol.ConnectionID]*zeroRTTQueue // only initialized if acceptEarlyConns == true
|
||||
|
@ -102,8 +102,8 @@ type baseServer struct {
|
|||
errorChan chan struct{}
|
||||
closed bool
|
||||
running chan struct{} // closed as soon as run() returns
|
||||
versionNegotiationQueue chan *receivedPacket
|
||||
invalidTokenQueue chan *receivedPacket
|
||||
versionNegotiationQueue chan receivedPacket
|
||||
invalidTokenQueue chan receivedPacket
|
||||
|
||||
connQueue chan quicConn
|
||||
connQueueLen int32 // to be used as an atomic
|
||||
|
@ -160,8 +160,7 @@ func (l *EarlyListener) Addr() net.Addr {
|
|||
}
|
||||
|
||||
// ListenAddr creates a QUIC server listening on a given address.
|
||||
// The tls.Config must not be nil and must contain a certificate configuration.
|
||||
// The quic.Config may be nil, in that case the default values will be used.
|
||||
// See Listen for more details.
|
||||
func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (*Listener, error) {
|
||||
conn, err := listenUDP(addr)
|
||||
if err != nil {
|
||||
|
@ -195,16 +194,19 @@ func listenUDP(addr string) (*net.UDPConn, error) {
|
|||
return net.ListenUDP("udp", udpAddr)
|
||||
}
|
||||
|
||||
// Listen listens for QUIC connections on a given net.PacketConn. If the
|
||||
// PacketConn satisfies the OOBCapablePacketConn interface (as a net.UDPConn
|
||||
// does), ECN and packet info support will be enabled. In this case, ReadMsgUDP
|
||||
// and WriteMsgUDP will be used instead of ReadFrom and WriteTo to read/write
|
||||
// packets. A single net.PacketConn only be used for a single call to Listen.
|
||||
// The PacketConn can be used for simultaneous calls to Dial. QUIC connection
|
||||
// IDs are used for demultiplexing the different connections.
|
||||
// Listen listens for QUIC connections on a given net.PacketConn.
|
||||
// If the PacketConn satisfies the OOBCapablePacketConn interface (as a net.UDPConn does),
|
||||
// ECN and packet info support will be enabled. In this case, ReadMsgUDP and WriteMsgUDP
|
||||
// will be used instead of ReadFrom and WriteTo to read/write packets.
|
||||
// A single net.PacketConn can only be used for a single call to Listen.
|
||||
//
|
||||
// The tls.Config must not be nil and must contain a certificate configuration.
|
||||
// Furthermore, it must define an application control (using NextProtos).
|
||||
// The quic.Config may be nil, in that case the default values will be used.
|
||||
//
|
||||
// This is a convenience function. More advanced use cases should instantiate a Transport,
|
||||
// which offers configuration options for a more fine-grained control of the connection establishment,
|
||||
// including reusing the underlying UDP socket for outgoing QUIC connections.
|
||||
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*Listener, error) {
|
||||
tr := &Transport{Conn: conn, isSingleUse: true}
|
||||
return tr.Listen(tlsConf, config)
|
||||
|
@ -240,9 +242,9 @@ func newServer(
|
|||
connQueue: make(chan quicConn),
|
||||
errorChan: make(chan struct{}),
|
||||
running: make(chan struct{}),
|
||||
receivedPackets: make(chan *receivedPacket, protocol.MaxServerUnprocessedPackets),
|
||||
versionNegotiationQueue: make(chan *receivedPacket, 4),
|
||||
invalidTokenQueue: make(chan *receivedPacket, 4),
|
||||
receivedPackets: make(chan receivedPacket, protocol.MaxServerUnprocessedPackets),
|
||||
versionNegotiationQueue: make(chan receivedPacket, 4),
|
||||
invalidTokenQueue: make(chan receivedPacket, 4),
|
||||
newConn: newConnection,
|
||||
tracer: tracer,
|
||||
logger: utils.DefaultLogger.WithPrefix("server"),
|
||||
|
@ -343,7 +345,7 @@ func (s *baseServer) Addr() net.Addr {
|
|||
return s.conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (s *baseServer) handlePacket(p *receivedPacket) {
|
||||
func (s *baseServer) handlePacket(p receivedPacket) {
|
||||
select {
|
||||
case s.receivedPackets <- p:
|
||||
default:
|
||||
|
@ -354,7 +356,7 @@ func (s *baseServer) handlePacket(p *receivedPacket) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *baseServer) handlePacketImpl(p *receivedPacket) bool /* is the buffer still in use? */ {
|
||||
func (s *baseServer) handlePacketImpl(p receivedPacket) bool /* is the buffer still in use? */ {
|
||||
if !s.nextZeroRTTCleanup.IsZero() && p.rcvTime.After(s.nextZeroRTTCleanup) {
|
||||
defer s.cleanupZeroRTTQueues(p.rcvTime)
|
||||
}
|
||||
|
@ -444,7 +446,7 @@ func (s *baseServer) handlePacketImpl(p *receivedPacket) bool /* is the buffer s
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *baseServer) handle0RTTPacket(p *receivedPacket) bool {
|
||||
func (s *baseServer) handle0RTTPacket(p receivedPacket) bool {
|
||||
connID, err := wire.ParseConnectionID(p.data, 0)
|
||||
if err != nil {
|
||||
if s.tracer != nil {
|
||||
|
@ -476,7 +478,7 @@ func (s *baseServer) handle0RTTPacket(p *receivedPacket) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
queue := &zeroRTTQueue{packets: make([]*receivedPacket, 1, 8)}
|
||||
queue := &zeroRTTQueue{packets: make([]receivedPacket, 1, 8)}
|
||||
queue.packets[0] = p
|
||||
expiration := p.rcvTime.Add(protocol.Max0RTTQueueingDuration)
|
||||
queue.expiration = expiration
|
||||
|
@ -532,7 +534,7 @@ func (s *baseServer) validateToken(token *handshake.Token, addr net.Addr) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *baseServer) handleInitialImpl(p *receivedPacket, hdr *wire.Header) error {
|
||||
func (s *baseServer) handleInitialImpl(p receivedPacket, hdr *wire.Header) error {
|
||||
if len(hdr.Token) == 0 && hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
|
||||
p.buffer.Release()
|
||||
if s.tracer != nil {
|
||||
|
@ -630,7 +632,7 @@ func (s *baseServer) handleInitialImpl(p *receivedPacket, hdr *wire.Header) erro
|
|||
tracer = config.Tracer(context.WithValue(context.Background(), ConnectionTracingKey, tracingID), protocol.PerspectiveServer, connID)
|
||||
}
|
||||
conn = s.newConn(
|
||||
newSendConn(s.conn, p.remoteAddr, p.info),
|
||||
newSendConnWithPacketInfo(s.conn, p.remoteAddr, p.info),
|
||||
s.connHandler,
|
||||
origDestConnID,
|
||||
retrySrcConnID,
|
||||
|
@ -704,7 +706,7 @@ func (s *baseServer) handleNewConn(conn quicConn) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *baseServer) sendRetry(remoteAddr net.Addr, hdr *wire.Header, info *packetInfo) error {
|
||||
func (s *baseServer) sendRetry(remoteAddr net.Addr, hdr *wire.Header, info packetInfo) error {
|
||||
// Log the Initial packet now.
|
||||
// If no Retry is sent, the packet will be logged by the connection.
|
||||
(&wire.ExtendedHeader{Header: *hdr}).Log(s.logger)
|
||||
|
@ -740,11 +742,11 @@ func (s *baseServer) sendRetry(remoteAddr net.Addr, hdr *wire.Header, info *pack
|
|||
if s.tracer != nil {
|
||||
s.tracer.SentPacket(remoteAddr, &replyHdr.Header, protocol.ByteCount(len(buf.Data)), nil)
|
||||
}
|
||||
_, err = s.conn.WritePacket(buf.Data, remoteAddr, info.OOB())
|
||||
_, err = s.conn.WritePacket(buf.Data, uint16(len(buf.Data)), remoteAddr, info.OOB())
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *baseServer) enqueueInvalidToken(p *receivedPacket) {
|
||||
func (s *baseServer) enqueueInvalidToken(p receivedPacket) {
|
||||
select {
|
||||
case s.invalidTokenQueue <- p:
|
||||
default:
|
||||
|
@ -753,7 +755,7 @@ func (s *baseServer) enqueueInvalidToken(p *receivedPacket) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *baseServer) maybeSendInvalidToken(p *receivedPacket) {
|
||||
func (s *baseServer) maybeSendInvalidToken(p receivedPacket) {
|
||||
defer p.buffer.Release()
|
||||
|
||||
hdr, _, _, err := wire.ParsePacket(p.data)
|
||||
|
@ -770,6 +772,8 @@ func (s *baseServer) maybeSendInvalidToken(p *receivedPacket) {
|
|||
sealer, opener := handshake.NewInitialAEAD(hdr.DestConnectionID, protocol.PerspectiveServer, hdr.Version)
|
||||
data := p.data[:hdr.ParsedLen()+hdr.Length]
|
||||
extHdr, err := unpackLongHeader(opener, hdr, data, hdr.Version)
|
||||
// Only send INVALID_TOKEN if we can unprotect the packet.
|
||||
// This makes sure that we won't send it for packets that were corrupted.
|
||||
if err != nil {
|
||||
if s.tracer != nil {
|
||||
s.tracer.DroppedPacket(p.remoteAddr, logging.PacketTypeInitial, p.Size(), logging.PacketDropHeaderParseError)
|
||||
|
@ -791,13 +795,13 @@ func (s *baseServer) maybeSendInvalidToken(p *receivedPacket) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *baseServer) sendConnectionRefused(remoteAddr net.Addr, hdr *wire.Header, info *packetInfo) error {
|
||||
func (s *baseServer) sendConnectionRefused(remoteAddr net.Addr, hdr *wire.Header, info packetInfo) error {
|
||||
sealer, _ := handshake.NewInitialAEAD(hdr.DestConnectionID, protocol.PerspectiveServer, hdr.Version)
|
||||
return s.sendError(remoteAddr, hdr, sealer, qerr.ConnectionRefused, info)
|
||||
}
|
||||
|
||||
// sendError sends the error as a response to the packet received with header hdr
|
||||
func (s *baseServer) sendError(remoteAddr net.Addr, hdr *wire.Header, sealer handshake.LongHeaderSealer, errorCode qerr.TransportErrorCode, info *packetInfo) error {
|
||||
func (s *baseServer) sendError(remoteAddr net.Addr, hdr *wire.Header, sealer handshake.LongHeaderSealer, errorCode qerr.TransportErrorCode, info packetInfo) error {
|
||||
b := getPacketBuffer()
|
||||
defer b.Release()
|
||||
|
||||
|
@ -837,11 +841,11 @@ func (s *baseServer) sendError(remoteAddr net.Addr, hdr *wire.Header, sealer han
|
|||
if s.tracer != nil {
|
||||
s.tracer.SentPacket(remoteAddr, &replyHdr.Header, protocol.ByteCount(len(b.Data)), []logging.Frame{ccf})
|
||||
}
|
||||
_, err = s.conn.WritePacket(b.Data, remoteAddr, info.OOB())
|
||||
_, err = s.conn.WritePacket(b.Data, uint16(len(b.Data)), remoteAddr, info.OOB())
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *baseServer) enqueueVersionNegotiationPacket(p *receivedPacket) (bufferInUse bool) {
|
||||
func (s *baseServer) enqueueVersionNegotiationPacket(p receivedPacket) (bufferInUse bool) {
|
||||
select {
|
||||
case s.versionNegotiationQueue <- p:
|
||||
return true
|
||||
|
@ -851,7 +855,7 @@ func (s *baseServer) enqueueVersionNegotiationPacket(p *receivedPacket) (bufferI
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *baseServer) maybeSendVersionNegotiationPacket(p *receivedPacket) {
|
||||
func (s *baseServer) maybeSendVersionNegotiationPacket(p receivedPacket) {
|
||||
defer p.buffer.Release()
|
||||
|
||||
v, err := wire.ParseVersion(p.data)
|
||||
|
@ -875,7 +879,7 @@ func (s *baseServer) maybeSendVersionNegotiationPacket(p *receivedPacket) {
|
|||
if s.tracer != nil {
|
||||
s.tracer.SentVersionNegotiationPacket(p.remoteAddr, src, dest, s.config.Versions)
|
||||
}
|
||||
if _, err := s.conn.WritePacket(data, p.remoteAddr, p.info.OOB()); err != nil {
|
||||
if _, err := s.conn.WritePacket(data, uint16(len(data)), p.remoteAddr, p.info.OOB()); err != nil {
|
||||
s.logger.Debugf("Error sending Version Negotiation: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/github.com/quic-go/quic-go/stream.go
generated
vendored
2
vendor/github.com/quic-go/quic-go/stream.go
generated
vendored
|
@ -60,7 +60,7 @@ type streamI interface {
|
|||
// for sending
|
||||
hasData() bool
|
||||
handleStopSendingFrame(*wire.StopSendingFrame)
|
||||
popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (*ackhandler.Frame, bool)
|
||||
popStreamFrame(maxBytes protocol.ByteCount, v protocol.VersionNumber) (ackhandler.StreamFrame, bool, bool)
|
||||
updateSendWindow(protocol.ByteCount)
|
||||
}
|
||||
|
||||
|
|
48
vendor/github.com/quic-go/quic-go/sys_conn.go
generated
vendored
48
vendor/github.com/quic-go/quic-go/sys_conn.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
"time"
|
||||
|
@ -15,16 +16,38 @@ import (
|
|||
type OOBCapablePacketConn interface {
|
||||
net.PacketConn
|
||||
SyscallConn() (syscall.RawConn, error)
|
||||
SetReadBuffer(int) error
|
||||
ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
|
||||
WriteMsgUDP(b, oob []byte, addr *net.UDPAddr) (n, oobn int, err error)
|
||||
}
|
||||
|
||||
var _ OOBCapablePacketConn = &net.UDPConn{}
|
||||
|
||||
func wrapConn(pc net.PacketConn) (rawConn, error) {
|
||||
// OptimizeConn takes a net.PacketConn and attempts to enable various optimizations that will improve QUIC performance:
|
||||
// 1. It enables the Don't Fragment (DF) bit on the IP header.
|
||||
// This is required to run DPLPMTUD (Path MTU Discovery, RFC 8899).
|
||||
// 2. It enables reading of the ECN bits from the IP header.
|
||||
// This allows the remote node to speed up its loss detection and recovery.
|
||||
// 3. It uses batched syscalls (recvmmsg) to more efficiently receive packets from the socket.
|
||||
// 4. It uses Generic Segmentation Offload (GSO) to efficiently send batches of packets (on Linux).
|
||||
//
|
||||
// In order for this to work, the connection needs to implement the OOBCapablePacketConn interface (as a *net.UDPConn does).
|
||||
//
|
||||
// It's only necessary to call this function explicitly if the application calls WriteTo
|
||||
// after passing the connection to the Transport.
|
||||
func OptimizeConn(c net.PacketConn) (net.PacketConn, error) {
|
||||
return wrapConn(c)
|
||||
}
|
||||
|
||||
func wrapConn(pc net.PacketConn) (interface {
|
||||
net.PacketConn
|
||||
rawConn
|
||||
}, error,
|
||||
) {
|
||||
conn, ok := pc.(interface {
|
||||
SyscallConn() (syscall.RawConn, error)
|
||||
})
|
||||
var supportsDF bool
|
||||
if ok {
|
||||
rawConn, err := conn.SyscallConn()
|
||||
if err != nil {
|
||||
|
@ -33,7 +56,8 @@ func wrapConn(pc net.PacketConn) (rawConn, error) {
|
|||
|
||||
if _, ok := pc.LocalAddr().(*net.UDPAddr); ok {
|
||||
// Only set DF on sockets that we expect to be able to handle that configuration.
|
||||
err = setDF(rawConn)
|
||||
var err error
|
||||
supportsDF, err = setDF(rawConn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -42,32 +66,33 @@ func wrapConn(pc net.PacketConn) (rawConn, error) {
|
|||
c, ok := pc.(OOBCapablePacketConn)
|
||||
if !ok {
|
||||
utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.")
|
||||
return &basicConn{PacketConn: pc}, nil
|
||||
return &basicConn{PacketConn: pc, supportsDF: supportsDF}, nil
|
||||
}
|
||||
return newConn(c)
|
||||
return newConn(c, supportsDF)
|
||||
}
|
||||
|
||||
// The basicConn is the most trivial implementation of a connection.
|
||||
// The basicConn is the most trivial implementation of a rawConn.
|
||||
// It reads a single packet from the underlying net.PacketConn.
|
||||
// It is used when
|
||||
// * the net.PacketConn is not a OOBCapablePacketConn, and
|
||||
// * when the OS doesn't support OOB.
|
||||
type basicConn struct {
|
||||
net.PacketConn
|
||||
supportsDF bool
|
||||
}
|
||||
|
||||
var _ rawConn = &basicConn{}
|
||||
|
||||
func (c *basicConn) ReadPacket() (*receivedPacket, error) {
|
||||
func (c *basicConn) ReadPacket() (receivedPacket, error) {
|
||||
buffer := getPacketBuffer()
|
||||
// The packet size should not exceed protocol.MaxPacketBufferSize bytes
|
||||
// If it does, we only read a truncated packet, which will then end up undecryptable
|
||||
buffer.Data = buffer.Data[:protocol.MaxPacketBufferSize]
|
||||
n, addr, err := c.PacketConn.ReadFrom(buffer.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return receivedPacket{}, err
|
||||
}
|
||||
return &receivedPacket{
|
||||
return receivedPacket{
|
||||
remoteAddr: addr,
|
||||
rcvTime: time.Now(),
|
||||
data: buffer.Data[:n],
|
||||
|
@ -75,6 +100,11 @@ func (c *basicConn) ReadPacket() (*receivedPacket, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (c *basicConn) WritePacket(b []byte, addr net.Addr, _ []byte) (n int, err error) {
|
||||
func (c *basicConn) WritePacket(b []byte, packetSize uint16, addr net.Addr, _ []byte) (n int, err error) {
|
||||
if uint16(len(b)) != packetSize {
|
||||
panic(fmt.Sprintf("inconsistent length. got: %d. expected %d", packetSize, len(b)))
|
||||
}
|
||||
return c.PacketConn.WriteTo(b, addr)
|
||||
}
|
||||
|
||||
func (c *basicConn) capabilities() connCapabilities { return connCapabilities{DF: c.supportsDF} }
|
||||
|
|
8
vendor/github.com/quic-go/quic-go/sys_conn_df.go
generated
vendored
8
vendor/github.com/quic-go/quic-go/sys_conn_df.go
generated
vendored
|
@ -2,11 +2,13 @@
|
|||
|
||||
package quic
|
||||
|
||||
import "syscall"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func setDF(rawConn syscall.RawConn) error {
|
||||
func setDF(syscall.RawConn) (bool, error) {
|
||||
// no-op on unsupported platforms
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isMsgSizeErr(err error) bool {
|
||||
|
|
51
vendor/github.com/quic-go/quic-go/sys_conn_df_linux.go
generated
vendored
51
vendor/github.com/quic-go/quic-go/sys_conn_df_linux.go
generated
vendored
|
@ -4,14 +4,23 @@ package quic
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/quic-go/quic-go/internal/utils"
|
||||
)
|
||||
|
||||
func setDF(rawConn syscall.RawConn) error {
|
||||
// UDP_SEGMENT controls GSO (Generic Segmentation Offload)
|
||||
//
|
||||
//nolint:stylecheck
|
||||
const UDP_SEGMENT = 103
|
||||
|
||||
func setDF(rawConn syscall.RawConn) (bool, error) {
|
||||
// Enabling IP_MTU_DISCOVER will force the kernel to return "sendto: message too long"
|
||||
// and the datagram will not be fragmented
|
||||
var errDFIPv4, errDFIPv6 error
|
||||
|
@ -19,7 +28,7 @@ func setDF(rawConn syscall.RawConn) error {
|
|||
errDFIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_DO)
|
||||
errDFIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_DO)
|
||||
}); err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
switch {
|
||||
case errDFIPv4 == nil && errDFIPv6 == nil:
|
||||
|
@ -29,12 +38,46 @@ func setDF(rawConn syscall.RawConn) error {
|
|||
case errDFIPv4 != nil && errDFIPv6 == nil:
|
||||
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
|
||||
case errDFIPv4 != nil && errDFIPv6 != nil:
|
||||
return errors.New("setting DF failed for both IPv4 and IPv6")
|
||||
return false, errors.New("setting DF failed for both IPv4 and IPv6")
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func maybeSetGSO(rawConn syscall.RawConn) bool {
|
||||
disable, _ := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_GSO"))
|
||||
if disable {
|
||||
return false
|
||||
}
|
||||
|
||||
var setErr error
|
||||
if err := rawConn.Control(func(fd uintptr) {
|
||||
setErr = unix.SetsockoptInt(int(fd), syscall.IPPROTO_UDP, UDP_SEGMENT, 1)
|
||||
}); err != nil {
|
||||
setErr = err
|
||||
}
|
||||
if setErr != nil {
|
||||
log.Println("failed to enable GSO")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func isMsgSizeErr(err error) bool {
|
||||
// https://man7.org/linux/man-pages/man7/udp.7.html
|
||||
return errors.Is(err, unix.EMSGSIZE)
|
||||
}
|
||||
|
||||
func appendUDPSegmentSizeMsg(b []byte, size uint16) []byte {
|
||||
startLen := len(b)
|
||||
const dataLen = 2 // payload is a uint16
|
||||
b = append(b, make([]byte, unix.CmsgSpace(dataLen))...)
|
||||
h := (*unix.Cmsghdr)(unsafe.Pointer(&b[startLen]))
|
||||
h.Level = syscall.IPPROTO_UDP
|
||||
h.Type = UDP_SEGMENT
|
||||
h.SetLen(unix.CmsgLen(dataLen))
|
||||
|
||||
// UnixRights uses the private `data` method, but I *think* this achieves the same goal.
|
||||
offset := startLen + unix.CmsgSpace(0)
|
||||
*(*uint16)(unsafe.Pointer(&b[offset])) = size
|
||||
return b
|
||||
}
|
||||
|
|
17
vendor/github.com/quic-go/quic-go/sys_conn_df_windows.go
generated
vendored
17
vendor/github.com/quic-go/quic-go/sys_conn_df_windows.go
generated
vendored
|
@ -12,20 +12,23 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
// same for both IPv4 and IPv6 on Windows
|
||||
// IP_DONTFRAGMENT controls the Don't Fragment (DF) bit.
|
||||
//
|
||||
// It's the same code point for both IPv4 and IPv6 on Windows.
|
||||
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IP_DONTFRAG.html
|
||||
// https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IPV6_DONTFRAG.html
|
||||
//
|
||||
//nolint:stylecheck
|
||||
IP_DONTFRAGMENT = 14
|
||||
IPV6_DONTFRAG = 14
|
||||
)
|
||||
|
||||
func setDF(rawConn syscall.RawConn) error {
|
||||
func setDF(rawConn syscall.RawConn) (bool, error) {
|
||||
var errDFIPv4, errDFIPv6 error
|
||||
if err := rawConn.Control(func(fd uintptr) {
|
||||
errDFIPv4 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1)
|
||||
errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_DONTFRAG, 1)
|
||||
errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IP_DONTFRAGMENT, 1)
|
||||
}); err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
switch {
|
||||
case errDFIPv4 == nil && errDFIPv6 == nil:
|
||||
|
@ -35,9 +38,9 @@ func setDF(rawConn syscall.RawConn) error {
|
|||
case errDFIPv4 != nil && errDFIPv6 == nil:
|
||||
utils.DefaultLogger.Debugf("Setting DF for IPv6.")
|
||||
case errDFIPv4 != nil && errDFIPv6 != nil:
|
||||
return errors.New("setting DF failed for both IPv4 and IPv6")
|
||||
return false, errors.New("setting DF failed for both IPv4 and IPv6")
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func isMsgSizeErr(err error) bool {
|
||||
|
|
8
vendor/github.com/quic-go/quic-go/sys_conn_no_gso.go
generated
vendored
Normal file
8
vendor/github.com/quic-go/quic-go/sys_conn_no_gso.go
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
//go:build darwin || freebsd
|
||||
|
||||
package quic
|
||||
|
||||
import "syscall"
|
||||
|
||||
func maybeSetGSO(_ syscall.RawConn) bool { return false }
|
||||
func appendUDPSegmentSizeMsg(_ []byte, _ uint16) []byte { return nil }
|
13
vendor/github.com/quic-go/quic-go/sys_conn_no_oob.go
generated
vendored
13
vendor/github.com/quic-go/quic-go/sys_conn_no_oob.go
generated
vendored
|
@ -2,13 +2,20 @@
|
|||
|
||||
package quic
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
func newConn(c net.PacketConn) (rawConn, error) {
|
||||
return &basicConn{PacketConn: c}, nil
|
||||
func newConn(c net.PacketConn, supportsDF bool) (*basicConn, error) {
|
||||
return &basicConn{PacketConn: c, supportsDF: supportsDF}, nil
|
||||
}
|
||||
|
||||
func inspectReadBuffer(any) (int, error) { return 0, nil }
|
||||
func inspectWriteBuffer(any) (int, error) { return 0, nil }
|
||||
|
||||
type packetInfo struct {
|
||||
addr netip.Addr
|
||||
}
|
||||
|
||||
func (i *packetInfo) OOB() []byte { return nil }
|
||||
|
|
103
vendor/github.com/quic-go/quic-go/sys_conn_oob.go
generated
vendored
103
vendor/github.com/quic-go/quic-go/sys_conn_oob.go
generated
vendored
|
@ -5,7 +5,9 @@ package quic
|
|||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
@ -61,11 +63,13 @@ type oobConn struct {
|
|||
// Packets received from the kernel, but not yet returned by ReadPacket().
|
||||
messages []ipv4.Message
|
||||
buffers [batchSize]*packetBuffer
|
||||
|
||||
cap connCapabilities
|
||||
}
|
||||
|
||||
var _ rawConn = &oobConn{}
|
||||
|
||||
func newConn(c OOBCapablePacketConn) (*oobConn, error) {
|
||||
func newConn(c OOBCapablePacketConn, supportsDF bool) (*oobConn, error) {
|
||||
rawConn, err := c.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -122,6 +126,10 @@ func newConn(c OOBCapablePacketConn) (*oobConn, error) {
|
|||
bc = ipv4.NewPacketConn(c)
|
||||
}
|
||||
|
||||
// Try enabling GSO.
|
||||
// This will only succeed on Linux, and only for kernels > 4.18.
|
||||
supportsGSO := maybeSetGSO(rawConn)
|
||||
|
||||
msgs := make([]ipv4.Message, batchSize)
|
||||
for i := range msgs {
|
||||
// preallocate the [][]byte
|
||||
|
@ -133,13 +141,15 @@ func newConn(c OOBCapablePacketConn) (*oobConn, error) {
|
|||
messages: msgs,
|
||||
readPos: batchSize,
|
||||
}
|
||||
oobConn.cap.DF = supportsDF
|
||||
oobConn.cap.GSO = supportsGSO
|
||||
for i := 0; i < batchSize; i++ {
|
||||
oobConn.messages[i].OOB = make([]byte, oobBufferSize)
|
||||
}
|
||||
return oobConn, nil
|
||||
}
|
||||
|
||||
func (c *oobConn) ReadPacket() (*receivedPacket, error) {
|
||||
func (c *oobConn) ReadPacket() (receivedPacket, error) {
|
||||
if len(c.messages) == int(c.readPos) { // all messages read. Read the next batch of messages.
|
||||
c.messages = c.messages[:batchSize]
|
||||
// replace buffers data buffers up to the packet that has been consumed during the last ReadBatch call
|
||||
|
@ -153,7 +163,7 @@ func (c *oobConn) ReadPacket() (*receivedPacket, error) {
|
|||
|
||||
n, err := c.batchConn.ReadBatch(c.messages, 0)
|
||||
if n == 0 || err != nil {
|
||||
return nil, err
|
||||
return receivedPacket{}, err
|
||||
}
|
||||
c.messages = c.messages[:n]
|
||||
}
|
||||
|
@ -163,18 +173,21 @@ func (c *oobConn) ReadPacket() (*receivedPacket, error) {
|
|||
c.readPos++
|
||||
|
||||
data := msg.OOB[:msg.NN]
|
||||
var ecn protocol.ECN
|
||||
var destIP net.IP
|
||||
var ifIndex uint32
|
||||
p := receivedPacket{
|
||||
remoteAddr: msg.Addr,
|
||||
rcvTime: time.Now(),
|
||||
data: msg.Buffers[0][:msg.N],
|
||||
buffer: buffer,
|
||||
}
|
||||
for len(data) > 0 {
|
||||
hdr, body, remainder, err := unix.ParseOneSocketControlMessage(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return receivedPacket{}, err
|
||||
}
|
||||
if hdr.Level == unix.IPPROTO_IP {
|
||||
switch hdr.Type {
|
||||
case msgTypeIPTOS:
|
||||
ecn = protocol.ECN(body[0] & ecnMask)
|
||||
p.ecn = protocol.ECN(body[0] & ecnMask)
|
||||
case msgTypeIPv4PKTINFO:
|
||||
// struct in_pktinfo {
|
||||
// unsigned int ipi_ifindex; /* Interface index */
|
||||
|
@ -182,80 +195,94 @@ func (c *oobConn) ReadPacket() (*receivedPacket, error) {
|
|||
// struct in_addr ipi_addr; /* Header Destination
|
||||
// address */
|
||||
// };
|
||||
ip := make([]byte, 4)
|
||||
var ip [4]byte
|
||||
if len(body) == 12 {
|
||||
ifIndex = binary.LittleEndian.Uint32(body)
|
||||
copy(ip, body[8:12])
|
||||
copy(ip[:], body[8:12])
|
||||
p.info.ifIndex = binary.LittleEndian.Uint32(body)
|
||||
} else if len(body) == 4 {
|
||||
// FreeBSD
|
||||
copy(ip, body)
|
||||
copy(ip[:], body)
|
||||
}
|
||||
destIP = net.IP(ip)
|
||||
p.info.addr = netip.AddrFrom4(ip)
|
||||
}
|
||||
}
|
||||
if hdr.Level == unix.IPPROTO_IPV6 {
|
||||
switch hdr.Type {
|
||||
case unix.IPV6_TCLASS:
|
||||
ecn = protocol.ECN(body[0] & ecnMask)
|
||||
p.ecn = protocol.ECN(body[0] & ecnMask)
|
||||
case msgTypeIPv6PKTINFO:
|
||||
// struct in6_pktinfo {
|
||||
// struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||
// unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||
// };
|
||||
if len(body) == 20 {
|
||||
ip := make([]byte, 16)
|
||||
copy(ip, body[:16])
|
||||
destIP = net.IP(ip)
|
||||
ifIndex = binary.LittleEndian.Uint32(body[16:])
|
||||
var ip [16]byte
|
||||
copy(ip[:], body[:16])
|
||||
p.info.addr = netip.AddrFrom16(ip)
|
||||
p.info.ifIndex = binary.LittleEndian.Uint32(body[16:])
|
||||
}
|
||||
}
|
||||
}
|
||||
data = remainder
|
||||
}
|
||||
var info *packetInfo
|
||||
if destIP != nil {
|
||||
info = &packetInfo{
|
||||
addr: destIP,
|
||||
ifIndex: ifIndex,
|
||||
}
|
||||
}
|
||||
return &receivedPacket{
|
||||
remoteAddr: msg.Addr,
|
||||
rcvTime: time.Now(),
|
||||
data: msg.Buffers[0][:msg.N],
|
||||
ecn: ecn,
|
||||
info: info,
|
||||
buffer: buffer,
|
||||
}, nil
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (c *oobConn) WritePacket(b []byte, addr net.Addr, oob []byte) (n int, err error) {
|
||||
// WriteTo (re)implements the net.PacketConn method.
|
||||
// This is needed for users who call OptimizeConn to be able to send (non-QUIC) packets on the underlying connection.
|
||||
// With GSO enabled, this would otherwise not be needed, as the kernel requires the UDP_SEGMENT message to be set.
|
||||
func (c *oobConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
return c.WritePacket(p, uint16(len(p)), addr, nil)
|
||||
}
|
||||
|
||||
// WritePacket writes a new packet.
|
||||
// If the connection supports GSO (and we activated GSO support before),
|
||||
// it appends the UDP_SEGMENT size message to oob.
|
||||
// Callers are advised to make sure that oob has a sufficient capacity,
|
||||
// such that appending the UDP_SEGMENT size message doesn't cause an allocation.
|
||||
func (c *oobConn) WritePacket(b []byte, packetSize uint16, addr net.Addr, oob []byte) (n int, err error) {
|
||||
if c.cap.GSO {
|
||||
oob = appendUDPSegmentSizeMsg(oob, packetSize)
|
||||
} else if uint16(len(b)) != packetSize {
|
||||
panic(fmt.Sprintf("inconsistent length. got: %d. expected %d", packetSize, len(b)))
|
||||
}
|
||||
n, _, err = c.OOBCapablePacketConn.WriteMsgUDP(b, oob, addr.(*net.UDPAddr))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (c *oobConn) capabilities() connCapabilities {
|
||||
return c.cap
|
||||
}
|
||||
|
||||
type packetInfo struct {
|
||||
addr netip.Addr
|
||||
ifIndex uint32
|
||||
}
|
||||
|
||||
func (info *packetInfo) OOB() []byte {
|
||||
if info == nil {
|
||||
return nil
|
||||
}
|
||||
if ip4 := info.addr.To4(); ip4 != nil {
|
||||
if info.addr.Is4() {
|
||||
ip := info.addr.As4()
|
||||
// struct in_pktinfo {
|
||||
// unsigned int ipi_ifindex; /* Interface index */
|
||||
// struct in_addr ipi_spec_dst; /* Local address */
|
||||
// struct in_addr ipi_addr; /* Header Destination address */
|
||||
// };
|
||||
cm := ipv4.ControlMessage{
|
||||
Src: ip4,
|
||||
Src: ip[:],
|
||||
IfIndex: int(info.ifIndex),
|
||||
}
|
||||
return cm.Marshal()
|
||||
} else if len(info.addr) == 16 {
|
||||
} else if info.addr.Is6() {
|
||||
ip := info.addr.As16()
|
||||
// struct in6_pktinfo {
|
||||
// struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||
// unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||
// };
|
||||
cm := ipv6.ControlMessage{
|
||||
Src: info.addr,
|
||||
Src: ip[:],
|
||||
IfIndex: int(info.ifIndex),
|
||||
}
|
||||
return cm.Marshal()
|
||||
|
|
9
vendor/github.com/quic-go/quic-go/sys_conn_windows.go
generated
vendored
9
vendor/github.com/quic-go/quic-go/sys_conn_windows.go
generated
vendored
|
@ -3,13 +3,14 @@
|
|||
package quic
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func newConn(c OOBCapablePacketConn) (rawConn, error) {
|
||||
return &basicConn{PacketConn: c}, nil
|
||||
func newConn(c OOBCapablePacketConn, supportsDF bool) (*basicConn, error) {
|
||||
return &basicConn{PacketConn: c, supportsDF: supportsDF}, nil
|
||||
}
|
||||
|
||||
func inspectReadBuffer(c syscall.RawConn) (int, error) {
|
||||
|
@ -34,4 +35,8 @@ func inspectWriteBuffer(c syscall.RawConn) (int, error) {
|
|||
return size, serr
|
||||
}
|
||||
|
||||
type packetInfo struct {
|
||||
addr netip.Addr
|
||||
}
|
||||
|
||||
func (i *packetInfo) OOB() []byte { return nil }
|
||||
|
|
61
vendor/github.com/quic-go/quic-go/transport.go
generated
vendored
61
vendor/github.com/quic-go/quic-go/transport.go
generated
vendored
|
@ -20,14 +20,19 @@ import (
|
|||
"github.com/quic-go/quic-go/logging"
|
||||
)
|
||||
|
||||
// The Transport is the central point to manage incoming and outgoing QUIC connections.
|
||||
// QUIC demultiplexes connections based on their QUIC Connection IDs, not based on the 4-tuple.
|
||||
// This means that a single UDP socket can be used for listening for incoming connections, as well as
|
||||
// for dialing an arbitrary number of outgoing connections.
|
||||
// A Transport handles a single net.PacketConn, and offers a range of configuration options
|
||||
// compared to the simple helper functions like Listen and Dial that this package provides.
|
||||
type Transport struct {
|
||||
// A single net.PacketConn can only be handled by one Transport.
|
||||
// Bad things will happen if passed to multiple Transports.
|
||||
//
|
||||
// If the connection satisfies the OOBCapablePacketConn interface
|
||||
// (as a net.UDPConn does), ECN and packet info support will be enabled.
|
||||
// In this case, optimized syscalls might be used, skipping the
|
||||
// ReadFrom and WriteTo calls to read / write packets.
|
||||
// If not done by the user, the connection is passed through OptimizeConn to enable a number of optimizations.
|
||||
// After passing the connection to the Transport, it's invalid to call ReadFrom on the connection.
|
||||
// Calling WriteTo is only valid on the connection returned by OptimizeConn.
|
||||
Conn net.PacketConn
|
||||
|
||||
// The length of the connection ID in bytes.
|
||||
|
@ -44,6 +49,9 @@ type Transport struct {
|
|||
|
||||
// The StatelessResetKey is used to generate stateless reset tokens.
|
||||
// If no key is configured, sending of stateless resets is disabled.
|
||||
// It is highly recommended to configure a stateless reset key, as stateless resets
|
||||
// allow the peer to quickly recover from crashes and reboots of this node.
|
||||
// See section 10.3 of RFC 9000 for details.
|
||||
StatelessResetKey *StatelessResetKey
|
||||
|
||||
// A Tracer traces events that don't belong to a single QUIC connection.
|
||||
|
@ -67,7 +75,7 @@ type Transport struct {
|
|||
conn rawConn
|
||||
|
||||
closeQueue chan closePacket
|
||||
statelessResetQueue chan *receivedPacket
|
||||
statelessResetQueue chan receivedPacket
|
||||
|
||||
listening chan struct{} // is closed when listen returns
|
||||
closed bool
|
||||
|
@ -148,7 +156,7 @@ func (t *Transport) Dial(ctx context.Context, addr net.Addr, tlsConf *tls.Config
|
|||
if t.isSingleUse {
|
||||
onClose = func() { t.Close() }
|
||||
}
|
||||
return dial(ctx, newSendConn(t.conn, addr, nil), t.connIDGenerator, t.handlerMap, tlsConf, conf, onClose, false)
|
||||
return dial(ctx, newSendConn(t.conn, addr), t.connIDGenerator, t.handlerMap, tlsConf, conf, onClose, false)
|
||||
}
|
||||
|
||||
// DialEarly dials a new connection, attempting to use 0-RTT if possible.
|
||||
|
@ -164,18 +172,25 @@ func (t *Transport) DialEarly(ctx context.Context, addr net.Addr, tlsConf *tls.C
|
|||
if t.isSingleUse {
|
||||
onClose = func() { t.Close() }
|
||||
}
|
||||
return dial(ctx, newSendConn(t.conn, addr, nil), t.connIDGenerator, t.handlerMap, tlsConf, conf, onClose, true)
|
||||
return dial(ctx, newSendConn(t.conn, addr), t.connIDGenerator, t.handlerMap, tlsConf, conf, onClose, true)
|
||||
}
|
||||
|
||||
func (t *Transport) init(isServer bool) error {
|
||||
t.initOnce.Do(func() {
|
||||
getMultiplexer().AddConn(t.Conn)
|
||||
|
||||
conn, err := wrapConn(t.Conn)
|
||||
if err != nil {
|
||||
t.initErr = err
|
||||
return
|
||||
var conn rawConn
|
||||
if c, ok := t.Conn.(rawConn); ok {
|
||||
conn = c
|
||||
} else {
|
||||
var err error
|
||||
conn, err = wrapConn(t.Conn)
|
||||
if err != nil {
|
||||
t.initErr = err
|
||||
return
|
||||
}
|
||||
}
|
||||
t.conn = conn
|
||||
|
||||
t.logger = utils.DefaultLogger // TODO: make this configurable
|
||||
t.conn = conn
|
||||
|
@ -183,7 +198,7 @@ func (t *Transport) init(isServer bool) error {
|
|||
t.listening = make(chan struct{})
|
||||
|
||||
t.closeQueue = make(chan closePacket, 4)
|
||||
t.statelessResetQueue = make(chan *receivedPacket, 4)
|
||||
t.statelessResetQueue = make(chan receivedPacket, 4)
|
||||
|
||||
if t.ConnectionIDGenerator != nil {
|
||||
t.connIDGenerator = t.ConnectionIDGenerator
|
||||
|
@ -218,7 +233,7 @@ func (t *Transport) runSendQueue() {
|
|||
case <-t.listening:
|
||||
return
|
||||
case p := <-t.closeQueue:
|
||||
t.conn.WritePacket(p.payload, p.addr, p.info.OOB())
|
||||
t.conn.WritePacket(p.payload, uint16(len(p.payload)), p.addr, p.info.OOB())
|
||||
case p := <-t.statelessResetQueue:
|
||||
t.sendStatelessReset(p)
|
||||
}
|
||||
|
@ -230,14 +245,16 @@ func (t *Transport) runSendQueue() {
|
|||
func (t *Transport) Close() error {
|
||||
t.close(errors.New("closing"))
|
||||
if t.createdConn {
|
||||
if err := t.conn.Close(); err != nil {
|
||||
if err := t.Conn.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
} else if t.conn != nil {
|
||||
t.conn.SetReadDeadline(time.Now())
|
||||
defer func() { t.conn.SetReadDeadline(time.Time{}) }()
|
||||
}
|
||||
<-t.listening // wait until listening returns
|
||||
if t.listening != nil {
|
||||
<-t.listening // wait until listening returns
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -266,7 +283,9 @@ func (t *Transport) close(e error) {
|
|||
return
|
||||
}
|
||||
|
||||
t.handlerMap.Close(e)
|
||||
if t.handlerMap != nil {
|
||||
t.handlerMap.Close(e)
|
||||
}
|
||||
if t.server != nil {
|
||||
t.server.setCloseError(e)
|
||||
}
|
||||
|
@ -325,7 +344,7 @@ func (t *Transport) listen(conn rawConn) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Transport) handlePacket(p *receivedPacket) {
|
||||
func (t *Transport) handlePacket(p receivedPacket) {
|
||||
connID, err := wire.ParseConnectionID(p.data, t.connIDLen)
|
||||
if err != nil {
|
||||
t.logger.Debugf("error parsing connection ID on packet from %s: %s", p.remoteAddr, err)
|
||||
|
@ -357,7 +376,7 @@ func (t *Transport) handlePacket(p *receivedPacket) {
|
|||
t.server.handlePacket(p)
|
||||
}
|
||||
|
||||
func (t *Transport) maybeSendStatelessReset(p *receivedPacket) {
|
||||
func (t *Transport) maybeSendStatelessReset(p receivedPacket) {
|
||||
if t.StatelessResetKey == nil {
|
||||
p.buffer.Release()
|
||||
return
|
||||
|
@ -378,7 +397,7 @@ func (t *Transport) maybeSendStatelessReset(p *receivedPacket) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Transport) sendStatelessReset(p *receivedPacket) {
|
||||
func (t *Transport) sendStatelessReset(p receivedPacket) {
|
||||
defer p.buffer.Release()
|
||||
|
||||
connID, err := wire.ParseConnectionID(p.data, t.connIDLen)
|
||||
|
@ -392,7 +411,7 @@ func (t *Transport) sendStatelessReset(p *receivedPacket) {
|
|||
rand.Read(data)
|
||||
data[0] = (data[0] & 0x7f) | 0x40
|
||||
data = append(data, token[:]...)
|
||||
if _, err := t.conn.WritePacket(data, p.remoteAddr, p.info.OOB()); err != nil {
|
||||
if _, err := t.conn.WritePacket(data, uint16(len(data)), p.remoteAddr, p.info.OOB()); err != nil {
|
||||
t.logger.Debugf("Error sending Stateless Reset to %s: %s", p.remoteAddr, err)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue