fix: DoQ closes udp immediately.
This commit is contained in:
parent
947d9d4560
commit
a73e690172
1 changed files with 34 additions and 33 deletions
67
dns/doq.go
67
dns/doq.go
|
@ -25,9 +25,10 @@ var bytesPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }}
|
|||
type quicClient struct {
|
||||
addr string
|
||||
r *Resolver
|
||||
session quic.Connection
|
||||
connection quic.Connection
|
||||
proxyAdapter string
|
||||
sync.RWMutex // protects session and bytesPool
|
||||
udp net.PacketConn
|
||||
sync.RWMutex // protects connection and bytesPool
|
||||
}
|
||||
|
||||
func newDOQ(r *Resolver, addr, proxyAdapter string) *quicClient {
|
||||
|
@ -91,44 +92,43 @@ func isActive(s quic.Connection) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// getSession - opens or returns an existing quic.Connection
|
||||
// useCached - if true and cached session exists, return it right away
|
||||
// otherwise - forcibly creates a new session
|
||||
func (dc *quicClient) getSession(ctx context.Context) (quic.Connection, error) {
|
||||
var session quic.Connection
|
||||
// getConnection - opens or returns an existing quic.Connection
|
||||
// useCached - if true and cached connection exists, return it right away
|
||||
// otherwise - forcibly creates a new connection
|
||||
func (dc *quicClient) getConnection(ctx context.Context) (quic.Connection, error) {
|
||||
var connection quic.Connection
|
||||
dc.RLock()
|
||||
session = dc.session
|
||||
if session != nil && isActive(session) {
|
||||
connection = dc.connection
|
||||
|
||||
if connection != nil && isActive(connection) {
|
||||
dc.RUnlock()
|
||||
return session, nil
|
||||
}
|
||||
if session != nil {
|
||||
// we're recreating the session, let's create a new one
|
||||
_ = session.CloseWithError(0, "")
|
||||
return connection, nil
|
||||
}
|
||||
|
||||
dc.RUnlock()
|
||||
|
||||
dc.Lock()
|
||||
defer dc.Unlock()
|
||||
connection = dc.connection
|
||||
if connection != nil {
|
||||
if isActive(connection) {
|
||||
return connection, nil
|
||||
} else {
|
||||
_ = connection.CloseWithError(quic.ApplicationErrorCode(0), "")
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
session, err = dc.openSession(ctx)
|
||||
if err != nil {
|
||||
// This does not look too nice, but QUIC (or maybe quic-go)
|
||||
// doesn't seem stable enough.
|
||||
// Maybe retransmissions aren't fully implemented in quic-go?
|
||||
// Anyways, the simple solution is to make a second try when
|
||||
// it fails to open the QUIC session.
|
||||
session, err = dc.openSession(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
dc.session = session
|
||||
return session, nil
|
||||
connection, err = dc.openConnection(ctx)
|
||||
dc.connection = connection
|
||||
return connection, err
|
||||
}
|
||||
|
||||
func (dc *quicClient) openConnection(ctx context.Context) (quic.Connection, error) {
|
||||
if dc.udp != nil {
|
||||
_ = dc.udp.Close()
|
||||
}
|
||||
|
||||
func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error) {
|
||||
tlsConfig := tlsC.GetGlobalFingerprintTLCConfig(
|
||||
&tls.Config{
|
||||
InsecureSkipVerify: false,
|
||||
|
@ -142,10 +142,10 @@ func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error)
|
|||
ConnectionIDLength: 12,
|
||||
HandshakeIdleTimeout: time.Second * 8,
|
||||
MaxIncomingStreams: 4,
|
||||
MaxIdleTimeout: time.Second * 45,
|
||||
MaxIdleTimeout: time.Second * 30,
|
||||
}
|
||||
|
||||
log.Debugln("opening session to %s", dc.addr)
|
||||
log.Debugln("opening new connection to %s", dc.addr)
|
||||
var (
|
||||
udp net.PacketConn
|
||||
err error
|
||||
|
@ -186,14 +186,15 @@ func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error)
|
|||
|
||||
session, err := quic.DialContext(ctx, udp, &udpAddr, host, tlsConfig, quicConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open QUIC session: %w", err)
|
||||
return nil, fmt.Errorf("failed to open QUIC connection: %w", err)
|
||||
}
|
||||
|
||||
dc.udp = udp
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (dc *quicClient) openStream(ctx context.Context) (quic.Stream, error) {
|
||||
session, err := dc.getSession(ctx)
|
||||
session, err := dc.getConnection(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue