fix(doq): no keep-alive made no sense here
This commit is contained in:
@@ -279,7 +279,6 @@ func createClient(scheme, host, port, path string, opts Options) (DNSClient, err
|
|||||||
Host: host,
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
DNSSEC: opts.DNSSEC,
|
DNSSEC: opts.DNSSEC,
|
||||||
KeepAlive: opts.KeepAlive,
|
|
||||||
}
|
}
|
||||||
logger.Debug("Creating DoQ client with config: %+v", config)
|
logger.Debug("Creating DoQ client with config: %+v", config)
|
||||||
return doq.New(config)
|
return doq.New(config)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/afonsofrancof/sdns-proxy/common/logger"
|
"github.com/afonsofrancof/sdns-proxy/common/logger"
|
||||||
@@ -17,11 +16,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
Debug bool
|
Debug bool
|
||||||
DNSSEC bool
|
DNSSEC bool
|
||||||
KeepAlive bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@@ -32,11 +30,10 @@ type Client struct {
|
|||||||
quicTransport *quic.Transport
|
quicTransport *quic.Transport
|
||||||
quicConfig *quic.Config
|
quicConfig *quic.Config
|
||||||
config Config
|
config Config
|
||||||
connMutex sync.Mutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config Config) (*Client, error) {
|
func New(config Config) (*Client, error) {
|
||||||
logger.Debug("Creating DoQ client: %s:%s (KeepAlive: %v)", config.Host, config.Port, config.KeepAlive)
|
logger.Debug("Creating DoQ client: %s:%s", config.Host, config.Port)
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig := &tls.Config{
|
||||||
ServerName: config.Host,
|
ServerName: config.Host,
|
||||||
@@ -65,7 +62,9 @@ func New(config Config) (*Client, error) {
|
|||||||
MaxIdleTimeout: 30 * time.Second,
|
MaxIdleTimeout: 30 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &Client{
|
logger.Debug("DoQ client created: %s:%s (DNSSEC: %v)", config.Host, config.Port, config.DNSSEC)
|
||||||
|
|
||||||
|
return &Client{
|
||||||
targetAddr: targetAddr,
|
targetAddr: targetAddr,
|
||||||
tlsConfig: tlsConfig,
|
tlsConfig: tlsConfig,
|
||||||
udpConn: udpConn,
|
udpConn: udpConn,
|
||||||
@@ -73,52 +72,18 @@ func New(config Config) (*Client, error) {
|
|||||||
quicTransport: &quicTransport,
|
quicTransport: &quicTransport,
|
||||||
quicConfig: &quicConfig,
|
quicConfig: &quicConfig,
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}, nil
|
||||||
|
|
||||||
// If keep-alive is enabled, establish connection now
|
|
||||||
if config.KeepAlive {
|
|
||||||
if err := client.ensureConnection(); err != nil {
|
|
||||||
logger.Error("DoQ failed to establish initial connection: %v", err)
|
|
||||||
client.Close()
|
|
||||||
return nil, fmt.Errorf("failed to establish initial connection: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("DoQ client created: %s:%s (DNSSEC: %v, KeepAlive: %v)", config.Host, config.Port, config.DNSSEC, config.KeepAlive)
|
|
||||||
return client, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Close() {
|
func (c *Client) Close() {
|
||||||
logger.Debug("Closing DoQ client")
|
logger.Debug("Closing DoQ client")
|
||||||
c.connMutex.Lock()
|
|
||||||
defer c.connMutex.Unlock()
|
|
||||||
|
|
||||||
if c.quicConn != nil {
|
|
||||||
c.quicConn.CloseWithError(0, "client shutdown")
|
|
||||||
c.quicConn = nil
|
|
||||||
}
|
|
||||||
if c.udpConn != nil {
|
if c.udpConn != nil {
|
||||||
c.udpConn.Close()
|
c.udpConn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ensureConnection() error {
|
func (c *Client) OpenConnection() error {
|
||||||
c.connMutex.Lock()
|
logger.Debug("Opening DoQ connection to %s", c.targetAddr)
|
||||||
defer c.connMutex.Unlock()
|
|
||||||
|
|
||||||
// Check if existing connection is still valid
|
|
||||||
if c.quicConn != nil {
|
|
||||||
select {
|
|
||||||
case <-c.quicConn.Context().Done():
|
|
||||||
logger.Debug("DoQ connection closed, reconnecting")
|
|
||||||
c.quicConn = nil
|
|
||||||
default:
|
|
||||||
// Connection is still valid
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("Establishing DoQ connection to %s", c.targetAddr)
|
|
||||||
quicConn, err := c.quicTransport.DialEarly(context.Background(), c.targetAddr, c.tlsConfig, c.quicConfig)
|
quicConn, err := c.quicTransport.DialEarly(context.Background(), c.targetAddr, c.tlsConfig, c.quicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("DoQ connection failed to %s: %v", c.targetAddr, err)
|
logger.Error("DoQ connection failed to %s: %v", c.targetAddr, err)
|
||||||
@@ -136,19 +101,10 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) {
|
|||||||
logger.Debug("DoQ query: %s %s to %s", question.Name, dns.TypeToString[question.Qtype], c.targetAddr)
|
logger.Debug("DoQ query: %s %s to %s", question.Name, dns.TypeToString[question.Qtype], c.targetAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have a connection (either persistent or new)
|
if c.quicConn == nil {
|
||||||
if c.config.KeepAlive {
|
err := c.OpenConnection()
|
||||||
if err := c.ensureConnection(); err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("doq: failed to ensure connection: %w", err)
|
return nil, err
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// For non-keepalive mode, create a fresh connection for each query
|
|
||||||
c.connMutex.Lock()
|
|
||||||
c.quicConn = nil // Force new connection
|
|
||||||
c.connMutex.Unlock()
|
|
||||||
|
|
||||||
if err := c.ensureConnection(); err != nil {
|
|
||||||
return nil, fmt.Errorf("doq: failed to create connection: %w", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,33 +119,18 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) {
|
|||||||
return nil, fmt.Errorf("doq: failed to pack message: %w", err)
|
return nil, fmt.Errorf("doq: failed to pack message: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a stream for this query
|
var quicStream quic.Stream
|
||||||
c.connMutex.Lock()
|
quicStream, err = c.quicConn.OpenStream()
|
||||||
quicConn := c.quicConn
|
|
||||||
c.connMutex.Unlock()
|
|
||||||
|
|
||||||
quicStream, err := quicConn.OpenStream()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("DoQ failed to open stream: %v", err)
|
logger.Debug("DoQ stream failed, reconnecting: %v", err)
|
||||||
|
err = c.OpenConnection()
|
||||||
// If keep-alive is enabled, try to reconnect once
|
if err != nil {
|
||||||
if c.config.KeepAlive {
|
return nil, err
|
||||||
logger.Debug("DoQ stream failed with keep-alive, attempting reconnect")
|
}
|
||||||
if reconnectErr := c.ensureConnection(); reconnectErr != nil {
|
quicStream, err = c.quicConn.OpenStream()
|
||||||
return nil, fmt.Errorf("doq: failed to reconnect: %w", reconnectErr)
|
if err != nil {
|
||||||
}
|
logger.Error("DoQ failed to open stream after reconnect: %v", err)
|
||||||
|
return nil, err
|
||||||
c.connMutex.Lock()
|
|
||||||
quicConn = c.quicConn
|
|
||||||
c.connMutex.Unlock()
|
|
||||||
|
|
||||||
quicStream, err = quicConn.OpenStream()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("DoQ failed to open stream after reconnect: %v", err)
|
|
||||||
return nil, fmt.Errorf("doq: failed to open stream after reconnect: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("doq: failed to open stream: %w", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,15 +184,5 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) {
|
|||||||
logger.Debug("DoQ response from %s: %d answers", c.targetAddr, len(recvMsg.Answer))
|
logger.Debug("DoQ response from %s: %d answers", c.targetAddr, len(recvMsg.Answer))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the connection if not using keep-alive
|
|
||||||
if !c.config.KeepAlive {
|
|
||||||
c.connMutex.Lock()
|
|
||||||
if c.quicConn != nil {
|
|
||||||
c.quicConn.CloseWithError(0, "query complete")
|
|
||||||
c.quicConn = nil
|
|
||||||
}
|
|
||||||
c.connMutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
return recvMsg, nil
|
return recvMsg, nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user