Use a custom dialer for HTTP/3

This commit is contained in:
Frank Denis 2023-02-02 19:24:40 +01:00
parent 11e824bd13
commit 33c8027e0a
1 changed files with 32 additions and 4 deletions

View File

@ -22,8 +22,9 @@ import (
"github.com/jedisct1/dlog"
stamps "github.com/jedisct1/go-dnsstamps"
"github.com/quic-go/quic-go/http3"
"github.com/miekg/dns"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/http3"
"golang.org/x/net/http2"
netproxy "golang.org/x/net/proxy"
)
@ -155,7 +156,7 @@ func (xTransport *XTransport) rebuildTransport() {
ipOnly = "[" + cachedIP.String() + "]"
}
} else {
dlog.Debugf("[%s] IP address was not cached", host)
dlog.Debugf("[%s] IP address was not cached in DialContext", host)
}
addrStr = ipOnly + ":" + strconv.Itoa(port)
if xTransport.proxyDialer == nil {
@ -223,7 +224,31 @@ func (xTransport *XTransport) rebuildTransport() {
}
xTransport.transport = transport
if xTransport.http3 {
h3Transport := &http3.RoundTripper{DisableCompression: true, TLSClientConfig: &tlsClientConfig}
h3Transport := &http3.RoundTripper{DisableCompression: true, TLSClientConfig: &tlsClientConfig, Dial: func(ctx context.Context, addrStr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
dlog.Debugf("Dialing for H3: [%v]", addrStr)
host, port := ExtractHostAndPort(addrStr, stamps.DefaultPort)
ipOnly := host
cachedIP, _ := xTransport.loadCachedIP(host)
if cachedIP != nil {
if ipv4 := cachedIP.To4(); ipv4 != nil {
ipOnly = ipv4.String()
} else {
ipOnly = "[" + cachedIP.String() + "]"
}
} else {
dlog.Debugf("[%s] IP address was not cached in H3 DialContext", host)
}
addrStr = ipOnly + ":" + strconv.Itoa(port)
udpAddr, err := net.ResolveUDPAddr("udp", addrStr)
if err != nil {
return nil, err
}
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
if err != nil {
return nil, err
}
return quic.DialEarlyContext(ctx, udpConn, udpAddr, host, tlsCfg, cfg)
}}
xTransport.h3Transport = h3Transport
}
}
@ -401,7 +426,8 @@ func (xTransport *XTransport) Fetch(
hasAltSupport := false
if xTransport.h3Transport != nil {
xTransport.altSupport.RLock()
altPort, hasAltSupport := xTransport.altSupport.cache[url.Host]
var altPort uint16
altPort, hasAltSupport = xTransport.altSupport.cache[url.Host]
xTransport.altSupport.RUnlock()
if hasAltSupport {
if int(altPort) == port {
@ -456,6 +482,7 @@ func (xTransport *XTransport) Fetch(
err = errors.New(resp.Status)
}
} else {
dlog.Debugf("HTTP client error: [%v] - closing idle H3 connections", err)
(*xTransport.transport).CloseIdleConnections()
}
statusCode := 503
@ -496,6 +523,7 @@ func (xTransport *XTransport) Fetch(
}
xTransport.altSupport.Lock()
xTransport.altSupport.cache[url.Host] = altPort
dlog.Debugf("Caching altPort for [%v]", url.Host)
xTransport.altSupport.Unlock()
}
}