@@ -15,11 +15,11 @@ import (
1515 "syscall"
1616 "time"
1717
18- quic "github.com/quic-go/quic-go"
1918 "dev.c0redev.volter/internal/clientlog"
2019 "dev.c0redev.volter/internal/config"
2120 "dev.c0redev.volter/internal/protocol"
2221 "dev.c0redev.volter/internal/sockprotect"
22+ quic "github.com/quic-go/quic-go"
2323)
2424
2525type QUICConn = quic.Conn
@@ -147,20 +147,6 @@ func dialQUICConn(addr, serverName string, skipVerify bool, certPinSHA256 string
147147 return nil , nil , fmt .Errorf ("quic: bad udp port %q" , portStr )
148148 }
149149
150- resolveCtx , cancelRes := context .WithTimeout (context .Background (), 12 * time .Second )
151- ips , err := LookupHostIPsPreferV4 (resolveCtx , dialHost )
152- cancelRes ()
153- if err != nil {
154- return nil , nil , fmt .Errorf ("quic: resolve %q: %w" , dialHost , err )
155- }
156- if quicTraceOn () {
157- ipStrs := make ([]string , 0 , len (ips ))
158- for _ , ip := range ips {
159- ipStrs = append (ipStrs , ip .String ())
160- }
161- clientlog .Trace ("quic dial addr=%q sni=%q ips=%v" , addr , sniHost , ipStrs )
162- }
163-
164150 qconf := & quic.Config {
165151 EnableDatagrams : false ,
166152 MaxIdleTimeout : 15 * time .Minute ,
@@ -177,65 +163,88 @@ func dialQUICConn(addr, serverName string, skipVerify bool, certPinSHA256 string
177163 }
178164
179165 var lastErr error
180- for _ , ip := range ips {
181- dialCtx , cancelDial := context .WithTimeout (context .Background (), 50 * time .Second )
182- if v4 := ip .To4 (); v4 != nil {
183- remote := & net.UDPAddr {IP : v4 , Port : port }
166+ backoff := 250 * time .Millisecond
167+ for round := 0 ; round < 4 ; round ++ {
168+ resolveCtx , cancelRes := context .WithTimeout (context .Background (), 12 * time .Second )
169+ ips , err := LookupHostIPsPreferV4 (resolveCtx , dialHost )
170+ cancelRes ()
171+ if err != nil {
172+ lastErr = fmt .Errorf ("quic: resolve %q: %w" , dialHost , err )
173+ } else {
184174 if quicTraceOn () {
185- clientlog .Trace ("quic dial try Dial udp4 -> %s" , remote .String ())
175+ ipStrs := make ([]string , 0 , len (ips ))
176+ for _ , ip := range ips {
177+ ipStrs = append (ipStrs , ip .String ())
178+ }
179+ clientlog .Trace ("quic dial round=%d addr=%q sni=%q ips=%v" , round + 1 , addr , sniHost , ipStrs )
186180 }
187- pc , lerr := listenUDPForQUIC ("udp4" , & net.UDPAddr {IP : net .IPv4zero , Port : 0 })
188- if lerr != nil {
189- cancelDial ()
181+ for _ , ip := range ips {
182+ dialCtx , cancelDial := context .WithTimeout (context .Background (), 50 * time .Second )
183+ if v4 := ip .To4 (); v4 != nil {
184+ remote := & net.UDPAddr {IP : v4 , Port : port }
185+ if quicTraceOn () {
186+ clientlog .Trace ("quic dial try Dial udp4 -> %s" , remote .String ())
187+ }
188+ pc , lerr := listenUDPForQUIC ("udp4" , & net.UDPAddr {IP : net .IPv4zero , Port : 0 })
189+ if lerr != nil {
190+ cancelDial ()
191+ if quicTraceOn () {
192+ clientlog .Trace ("quic ListenUDP udp4: %v" , lerr )
193+ }
194+ lastErr = lerr
195+ continue
196+ }
197+ conn , derr := quic .Dial (dialCtx , pc , remote , tlsCfg , qconf )
198+ cancelDial ()
199+ if derr == nil {
200+ if quicTraceOn () {
201+ clientlog .Trace ("quic dial ok local=%s remote=%s" , conn .LocalAddr (), conn .RemoteAddr ())
202+ }
203+ closePC := func () { _ = pc .Close () }
204+ return conn , closePC , nil
205+ }
206+ _ = pc .Close ()
207+ if quicTraceOn () {
208+ clientlog .Trace ("quic dial fail Dial %s: %v" , remote .String (), derr )
209+ }
210+ lastErr = derr
211+ continue
212+ }
213+ pc , lerr := listenUDPForQUIC ("udp6" , & net.UDPAddr {IP : net .IPv6zero , Port : 0 })
214+ if lerr != nil {
215+ cancelDial ()
216+ if quicTraceOn () {
217+ clientlog .Trace ("quic dial ListenUDP udp6: %v" , lerr )
218+ }
219+ lastErr = lerr
220+ continue
221+ }
222+ udpAddr := & net.UDPAddr {IP : ip , Port : port }
190223 if quicTraceOn () {
191- clientlog .Trace ("quic ListenUDP udp4: %v " , lerr )
224+ clientlog .Trace ("quic dial try Dial udp6 local=%s -> %s " , pc . LocalAddr (), udpAddr )
192225 }
193- lastErr = lerr
194- continue
195- }
196- conn , derr := quic .Dial (dialCtx , pc , remote , tlsCfg , qconf )
197- cancelDial ()
198- if derr == nil {
226+ conn , derr := quic .Dial (dialCtx , pc , udpAddr , tlsCfg , qconf )
227+ cancelDial ()
228+ if derr == nil {
229+ if quicTraceOn () {
230+ clientlog .Trace ("quic dial ok local=%s remote=%s" , conn .LocalAddr (), conn .RemoteAddr ())
231+ }
232+ closePC := func () { _ = pc .Close () }
233+ return conn , closePC , nil
234+ }
235+ _ = pc .Close ()
199236 if quicTraceOn () {
200- clientlog .Trace ("quic dial ok local=%s remote=%s " , conn . LocalAddr (), conn . RemoteAddr () )
237+ clientlog .Trace ("quic dial fail Dial %s: %v " , udpAddr , derr )
201238 }
202- closePC := func () { _ = pc .Close () }
203- return conn , closePC , nil
204- }
205- _ = pc .Close ()
206- if quicTraceOn () {
207- clientlog .Trace ("quic dial fail Dial %s: %v" , remote .String (), derr )
208- }
209- lastErr = derr
210- continue
211- }
212- pc , lerr := listenUDPForQUIC ("udp6" , & net.UDPAddr {IP : net .IPv6zero , Port : 0 })
213- if lerr != nil {
214- cancelDial ()
215- if quicTraceOn () {
216- clientlog .Trace ("quic dial ListenUDP udp6: %v" , lerr )
239+ lastErr = derr
217240 }
218- lastErr = lerr
219- continue
220- }
221- udpAddr := & net.UDPAddr {IP : ip , Port : port }
222- if quicTraceOn () {
223- clientlog .Trace ("quic dial try Dial udp6 local=%s -> %s" , pc .LocalAddr (), udpAddr )
224241 }
225- conn , derr := quic .Dial (dialCtx , pc , udpAddr , tlsCfg , qconf )
226- cancelDial ()
227- if derr == nil {
228- if quicTraceOn () {
229- clientlog .Trace ("quic dial ok local=%s remote=%s" , conn .LocalAddr (), conn .RemoteAddr ())
242+ if round < 3 {
243+ time .Sleep (backoff )
244+ if backoff < 2 * time .Second {
245+ backoff *= 2
230246 }
231- closePC := func () { _ = pc .Close () }
232- return conn , closePC , nil
233- }
234- _ = pc .Close ()
235- if quicTraceOn () {
236- clientlog .Trace ("quic dial fail Dial %s: %v" , udpAddr , derr )
237247 }
238- lastErr = derr
239248 }
240249 return nil , nil , wrapQUICDialTLS (lastErr , addr , skipVerify , hasPin , rootCAs != nil )
241250}
0 commit comments