[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [meek/utls_2] utls: copy default timeouts etc. when using HTTP/1.
commit 52bc759ac35ade721c87f53ba2d341a68c715c32
Author: David Fifield <david@xxxxxxxxxxxxxxx>
Date: Thu Jan 31 00:22:11 2019 -0700
utls: copy default timeouts etc. when using HTTP/1.
Unfortunately I don't know a way to do the same for HTTP/2. Configuring
an http.Transport and then calling http2.ConfigureTransport on it
doesn't work; it leads to the same problem of an HTTP/1 client speaking
to an HTTP/2 server.
---
meek-client/utls.go | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/meek-client/utls.go b/meek-client/utls.go
index 9076549..2c9c52e 100644
--- a/meek-client/utls.go
+++ b/meek-client/utls.go
@@ -39,6 +39,7 @@ import (
"net"
"net/http"
"net/url"
+ "reflect"
"strings"
"sync"
@@ -46,6 +47,25 @@ import (
"golang.org/x/net/http2"
)
+// Copy the public fields (fields for which CanSet is true) from src to dst.
+// src and dst must be pointers to the same type. We use this to make copies of
+// httpRoundTripper. We cannot use struct assignment, because http.Transport
+// contains private mutexes. The idea of using reflection to copy only the
+// public fields comes from a post by Nick Craig-Wood:
+// https://groups.google.com/d/msg/Golang-Nuts/SDiGYNVE8iY/89hRKTF4BAAJ
+func copyPublicFields(dst, src interface{}) {
+ if reflect.TypeOf(dst) != reflect.TypeOf(src) {
+ panic("unequal types")
+ }
+ dstValue := reflect.ValueOf(dst).Elem()
+ srcValue := reflect.ValueOf(src).Elem()
+ for i := 0; i < dstValue.NumField(); i++ {
+ if dstValue.Field(i).CanSet() {
+ dstValue.Field(i).Set(srcValue.Field(i))
+ }
+ }
+}
+
// Extract a host:port address from a URL, suitable for passing to net.Dial.
func addrForDial(url *url.URL) (string, error) {
host := url.Hostname()
@@ -164,6 +184,10 @@ func makeRoundTripper(req *http.Request, clientHelloID *utls.ClientHelloID) (htt
// Construct an http.Transport or http2.Transport depending on ALPN.
switch protocol {
case http2.NextProtoTLS:
+ // Unfortunately http2.Transport does not expose the same
+ // configuration options as http.Transport with regard to
+ // timeouts, etc., so we are at the mercy of the defaults.
+ // https://github.com/golang/go/issues/16581
return &http2.Transport{
DialTLS: func(network, addr string, _ *tls.Config) (net.Conn, error) {
// Ignore the *tls.Config parameter; use our
@@ -172,8 +196,13 @@ func makeRoundTripper(req *http.Request, clientHelloID *utls.ClientHelloID) (htt
},
}, nil
default:
- // TODO: copy public fields from httpRoundTripper?
- return &http.Transport{DialTLS: dialTLS}, nil
+ // With http.Transport, copy important default fields from
+ // http.DefaultTransport, such as TLSHandshakeTimeout and
+ // IdleConnTimeout.
+ tr := &http.Transport{}
+ copyPublicFields(tr, httpRoundTripper)
+ tr.DialTLS = dialTLS
+ return tr, nil
}
}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits