commit 88fd7233036450e0d3278f3afe0a9995974ae120 Author: David Fifield david@bamsoftware.com Date: Wed Dec 29 21:35:06 2021 -0700
Only lock the assignment to rt.rt, not the whole RoundTrip.
We need to guard against concurrent modification of rt.rt, but once it is set, we many concurrently call rt.rt.RoundTrip. The way this was written before, it was preventing more than one RoundTrip from happening at once. (Which was not noticeable, because the protocol serialized all RoundTrips.) --- meek-client/utls.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/meek-client/utls.go b/meek-client/utls.go index bcd386f..1f3effb 100644 --- a/meek-client/utls.go +++ b/meek-client/utls.go @@ -94,11 +94,10 @@ func dialUTLS(network, addr string, cfg *utls.Config, clientHelloID *utls.Client // // Can only be reused among servers which negotiate the same ALPN. type UTLSRoundTripper struct { - sync.Mutex - clientHelloID *utls.ClientHelloID config *utls.Config proxyDialer proxy.Dialer + rtOnce sync.Once rt http.RoundTripper
// Transport for HTTP requests, which don't use uTLS. @@ -115,18 +114,16 @@ func (rt *UTLSRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) return nil, fmt.Errorf("unsupported URL scheme %q", req.URL.Scheme) }
- rt.Lock() - defer rt.Unlock() - - if rt.rt == nil { - // On the first call, make an http.Transport or http2.Transport - // as appropriate. - var err error + // On the first call, make an http.Transport or http2.Transport as + // appropriate. + var err error + rt.rtOnce.Do(func() { rt.rt, err = makeRoundTripper(req.URL, rt.clientHelloID, rt.config, rt.proxyDialer) - if err != nil { - return nil, err - } + }) + if err != nil { + return nil, err } + // Forward the request to the internal http.Transport or http2.Transport. return rt.rt.RoundTrip(req) }
tor-commits@lists.torproject.org