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 {
|
type quicClient struct {
|
||||||
addr string
|
addr string
|
||||||
r *Resolver
|
r *Resolver
|
||||||
session quic.Connection
|
connection quic.Connection
|
||||||
proxyAdapter string
|
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 {
|
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
|
// getConnection - opens or returns an existing quic.Connection
|
||||||
// useCached - if true and cached session exists, return it right away
|
// useCached - if true and cached connection exists, return it right away
|
||||||
// otherwise - forcibly creates a new session
|
// otherwise - forcibly creates a new connection
|
||||||
func (dc *quicClient) getSession(ctx context.Context) (quic.Connection, error) {
|
func (dc *quicClient) getConnection(ctx context.Context) (quic.Connection, error) {
|
||||||
var session quic.Connection
|
var connection quic.Connection
|
||||||
dc.RLock()
|
dc.RLock()
|
||||||
session = dc.session
|
connection = dc.connection
|
||||||
if session != nil && isActive(session) {
|
|
||||||
|
if connection != nil && isActive(connection) {
|
||||||
dc.RUnlock()
|
dc.RUnlock()
|
||||||
return session, nil
|
return connection, nil
|
||||||
}
|
|
||||||
if session != nil {
|
|
||||||
// we're recreating the session, let's create a new one
|
|
||||||
_ = session.CloseWithError(0, "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.RUnlock()
|
dc.RUnlock()
|
||||||
|
|
||||||
dc.Lock()
|
dc.Lock()
|
||||||
defer dc.Unlock()
|
defer dc.Unlock()
|
||||||
|
connection = dc.connection
|
||||||
var err error
|
if connection != nil {
|
||||||
session, err = dc.openSession(ctx)
|
if isActive(connection) {
|
||||||
if err != nil {
|
return connection, nil
|
||||||
// This does not look too nice, but QUIC (or maybe quic-go)
|
} else {
|
||||||
// doesn't seem stable enough.
|
_ = connection.CloseWithError(quic.ApplicationErrorCode(0), "")
|
||||||
// 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
|
var err error
|
||||||
|
connection, err = dc.openConnection(ctx)
|
||||||
|
dc.connection = connection
|
||||||
|
return connection, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error) {
|
func (dc *quicClient) openConnection(ctx context.Context) (quic.Connection, error) {
|
||||||
|
if dc.udp != nil {
|
||||||
|
_ = dc.udp.Close()
|
||||||
|
}
|
||||||
|
|
||||||
tlsConfig := tlsC.GetGlobalFingerprintTLCConfig(
|
tlsConfig := tlsC.GetGlobalFingerprintTLCConfig(
|
||||||
&tls.Config{
|
&tls.Config{
|
||||||
InsecureSkipVerify: false,
|
InsecureSkipVerify: false,
|
||||||
|
@ -142,10 +142,10 @@ func (dc *quicClient) openSession(ctx context.Context) (quic.Connection, error)
|
||||||
ConnectionIDLength: 12,
|
ConnectionIDLength: 12,
|
||||||
HandshakeIdleTimeout: time.Second * 8,
|
HandshakeIdleTimeout: time.Second * 8,
|
||||||
MaxIncomingStreams: 4,
|
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 (
|
var (
|
||||||
udp net.PacketConn
|
udp net.PacketConn
|
||||||
err error
|
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)
|
session, err := quic.DialContext(ctx, udp, &udpAddr, host, tlsConfig, quicConfig)
|
||||||
if err != nil {
|
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
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *quicClient) openStream(ctx context.Context) (quic.Stream, error) {
|
func (dc *quicClient) openStream(ctx context.Context) (quic.Stream, error) {
|
||||||
session, err := dc.getSession(ctx)
|
session, err := dc.getConnection(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue