mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
upstream: sync to 0.39.1
This commit is contained in:
commit
7c77243b04
147 changed files with 3740 additions and 2211 deletions
89
transport.go
89
transport.go
|
@ -17,6 +17,8 @@ import (
|
|||
"github.com/refraction-networking/uquic/logging"
|
||||
)
|
||||
|
||||
var errListenerAlreadySet = errors.New("listener already set")
|
||||
|
||||
// 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
|
||||
|
@ -58,8 +60,26 @@ type Transport struct {
|
|||
// See section 10.3 of RFC 9000 for details.
|
||||
StatelessResetKey *StatelessResetKey
|
||||
|
||||
// The TokenGeneratorKey is used to encrypt session resumption tokens.
|
||||
// If no key is configured, a random key will be generated.
|
||||
// If multiple servers are authoritative for the same domain, they should use the same key,
|
||||
// see section 8.1.3 of RFC 9000 for details.
|
||||
TokenGeneratorKey *TokenGeneratorKey
|
||||
|
||||
// MaxTokenAge is the maximum age of the resumption token presented during the handshake.
|
||||
// These tokens allow skipping address resumption when resuming a QUIC connection,
|
||||
// and are especially useful when using 0-RTT.
|
||||
// If not set, it defaults to 24 hours.
|
||||
// See section 8.1.3 of RFC 9000 for details.
|
||||
MaxTokenAge time.Duration
|
||||
|
||||
// DisableVersionNegotiationPackets disables the sending of Version Negotiation packets.
|
||||
// This can be useful if version information is exchanged out-of-band.
|
||||
// It has no effect for clients.
|
||||
DisableVersionNegotiationPackets bool
|
||||
|
||||
// A Tracer traces events that don't belong to a single QUIC connection.
|
||||
Tracer logging.Tracer
|
||||
Tracer *logging.Tracer
|
||||
|
||||
handlerMap packetHandlerManager
|
||||
|
||||
|
@ -74,7 +94,7 @@ type Transport struct {
|
|||
// If no ConnectionIDGenerator is set, this is set to a default.
|
||||
connIDGenerator ConnectionIDGenerator
|
||||
|
||||
server unknownPacketHandler
|
||||
server *baseServer
|
||||
|
||||
conn rawConn
|
||||
|
||||
|
@ -96,28 +116,10 @@ type Transport struct {
|
|||
// There can only be a single listener on any net.PacketConn.
|
||||
// Listen may only be called again after the current Listener was closed.
|
||||
func (t *Transport) Listen(tlsConf *tls.Config, conf *Config) (*Listener, error) {
|
||||
if tlsConf == nil {
|
||||
return nil, errors.New("quic: tls.Config not set")
|
||||
}
|
||||
if err := validateConfig(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.mutex.Lock()
|
||||
defer t.mutex.Unlock()
|
||||
|
||||
if t.server != nil {
|
||||
return nil, errListenerAlreadySet
|
||||
}
|
||||
conf = populateServerConfig(conf)
|
||||
if err := t.init(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := newServer(t.conn, t.handlerMap, t.connIDGenerator, tlsConf, conf, t.Tracer, t.closeServer, false)
|
||||
s, err := t.createServer(tlsConf, conf, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.server = s
|
||||
return &Listener{baseServer: s}, nil
|
||||
}
|
||||
|
||||
|
@ -125,6 +127,14 @@ func (t *Transport) Listen(tlsConf *tls.Config, conf *Config) (*Listener, error)
|
|||
// There can only be a single listener on any net.PacketConn.
|
||||
// Listen may only be called again after the current Listener was closed.
|
||||
func (t *Transport) ListenEarly(tlsConf *tls.Config, conf *Config) (*EarlyListener, error) {
|
||||
s, err := t.createServer(tlsConf, conf, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EarlyListener{baseServer: s}, nil
|
||||
}
|
||||
|
||||
func (t *Transport) createServer(tlsConf *tls.Config, conf *Config, allow0RTT bool) (*baseServer, error) {
|
||||
if tlsConf == nil {
|
||||
return nil, errors.New("quic: tls.Config not set")
|
||||
}
|
||||
|
@ -142,12 +152,21 @@ func (t *Transport) ListenEarly(tlsConf *tls.Config, conf *Config) (*EarlyListen
|
|||
if err := t.init(false); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s, err := newServer(t.conn, t.handlerMap, t.connIDGenerator, tlsConf, conf, t.Tracer, t.closeServer, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := newServer(
|
||||
t.conn,
|
||||
t.handlerMap,
|
||||
t.connIDGenerator,
|
||||
tlsConf,
|
||||
conf,
|
||||
t.Tracer,
|
||||
t.closeServer,
|
||||
*t.TokenGeneratorKey,
|
||||
t.MaxTokenAge,
|
||||
t.DisableVersionNegotiationPackets,
|
||||
allow0RTT,
|
||||
)
|
||||
t.server = s
|
||||
return &EarlyListener{baseServer: s}, nil
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Dial dials a new connection to a remote host (not using 0-RTT).
|
||||
|
@ -200,6 +219,14 @@ func (t *Transport) init(allowZeroLengthConnIDs bool) error {
|
|||
|
||||
t.closeQueue = make(chan closePacket, 4)
|
||||
t.statelessResetQueue = make(chan receivedPacket, 4)
|
||||
if t.TokenGeneratorKey == nil {
|
||||
var key TokenGeneratorKey
|
||||
if _, err := rand.Read(key[:]); err != nil {
|
||||
t.initErr = err
|
||||
return
|
||||
}
|
||||
t.TokenGeneratorKey = &key
|
||||
}
|
||||
|
||||
if t.ConnectionIDGenerator != nil {
|
||||
t.connIDGenerator = t.ConnectionIDGenerator
|
||||
|
@ -225,7 +252,7 @@ func (t *Transport) WriteTo(b []byte, addr net.Addr) (int, error) {
|
|||
if err := t.init(false); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return t.conn.WritePacket(b, addr, nil)
|
||||
return t.conn.WritePacket(b, addr, nil, 0, protocol.ECNUnsupported)
|
||||
}
|
||||
|
||||
func (t *Transport) enqueueClosePacket(p closePacket) {
|
||||
|
@ -243,7 +270,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, p.addr, p.info.OOB(), 0, protocol.ECNUnsupported)
|
||||
case p := <-t.statelessResetQueue:
|
||||
t.sendStatelessReset(p)
|
||||
}
|
||||
|
@ -348,7 +375,7 @@ 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)
|
||||
if t.Tracer != nil {
|
||||
if t.Tracer != nil && t.Tracer.DroppedPacket != nil {
|
||||
t.Tracer.DroppedPacket(p.remoteAddr, logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropHeaderParseError)
|
||||
}
|
||||
p.buffer.MaybeRelease()
|
||||
|
@ -411,7 +438,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, p.remoteAddr, p.info.OOB(), 0, protocol.ECNUnsupported); err != nil {
|
||||
t.logger.Debugf("Error sending Stateless Reset to %s: %s", p.remoteAddr, err)
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +470,7 @@ func (t *Transport) handleNonQUICPacket(p receivedPacket) {
|
|||
select {
|
||||
case t.nonQUICPackets <- p:
|
||||
default:
|
||||
if t.Tracer != nil {
|
||||
if t.Tracer != nil && t.Tracer.DroppedPacket != nil {
|
||||
t.Tracer.DroppedPacket(p.remoteAddr, logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropDOSPrevention)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue