From 3d5a8ee7d3fea95fe897dc5983ec8a1afc5a04ab Mon Sep 17 00:00:00 2001 From: iseki Date: Wed, 14 Dec 2022 05:37:03 +0000 Subject: [PATCH 1/7] internal/socks: permit authenticating with an empty password The behavior is accepted widely, and I found no reason to deny it. Fixes golang/go#57285 Change-Id: I39b07295cc89481ea0d6b70b71f2aa57f1a01407 GitHub-Last-Rev: b00ecb1d7afd1f0ae60d2215f33161e535931eb4 GitHub-Pull-Request: golang/net#157 Reviewed-on: https://go-review.googlesource.com/c/net/+/457355 Run-TryBot: Damien Neil Auto-Submit: Damien Neil TryBot-Result: Gopher Robot Reviewed-by: Than McIntosh Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- internal/socks/socks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/socks/socks.go b/internal/socks/socks.go index 97db2340e..84fcc32b6 100644 --- a/internal/socks/socks.go +++ b/internal/socks/socks.go @@ -289,7 +289,7 @@ func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, case AuthMethodNotRequired: return nil case AuthMethodUsernamePassword: - if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 { + if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) > 255 { return errors.New("invalid username/password") } b := []byte{authUsernamePasswordVersion} From 9001ca7de9d738aed247bf005debccb5b186a965 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 9 Apr 2023 10:25:29 +0200 Subject: [PATCH 2/7] nettest: re-enable unixpacket tests on netbsd/386 The tests seem to work fine on netbsd/386 (NetBSD 9.3). This reverts CL 80755. Updates golang/go#22927 Change-Id: I480ac82b10e85aa0fc081e76fbbcbc75f3ee7d38 Reviewed-on: https://go-review.googlesource.com/c/net/+/483375 Auto-Submit: Tobias Klauser Reviewed-by: Benny Siegert Reviewed-by: David Chase Run-TryBot: Tobias Klauser TryBot-Result: Gopher Robot --- nettest/nettest.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nettest/nettest.go b/nettest/nettest.go index 510555ac2..1e350f09c 100644 --- a/nettest/nettest.go +++ b/nettest/nettest.go @@ -126,12 +126,6 @@ func TestableNetwork(network string) bool { switch runtime.GOOS { case "aix", "android", "fuchsia", "hurd", "darwin", "ios", "js", "nacl", "plan9", "windows", "zos": return false - case "netbsd": - // It passes on amd64 at least. 386 fails - // (Issue 22927). arm is unknown. - if runtime.GOARCH == "386" { - return false - } } } switch ss[0] { From eb1572ce7f7a6e97ec44c27568286345c2a7748e Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 14 Apr 2023 12:13:47 -0700 Subject: [PATCH 3/7] html: another shot at security doc Be clearer about the operation of the tokenizer and the parser (and their differences), and be explicit about the need for re-serialization when they are being used in security contexts. Change-Id: Ieb8f2a9d4806fb7a8849a15671667396e81c53b9 Reviewed-on: https://go-review.googlesource.com/c/net/+/484795 Auto-Submit: Roland Shoemaker Reviewed-by: Damien Neil Run-TryBot: Roland Shoemaker TryBot-Result: Gopher Robot --- html/doc.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/html/doc.go b/html/doc.go index 5ff8480cf..2466ae3d9 100644 --- a/html/doc.go +++ b/html/doc.go @@ -99,14 +99,20 @@ Care should be taken when parsing and interpreting HTML, whether full documents or fragments, within the framework of the HTML specification, especially with regard to untrusted inputs. -This package provides both a tokenizer and a parser. Only the parser constructs -a DOM according to the HTML specification, resolving malformed and misplaced -tags where appropriate. The tokenizer simply tokenizes the HTML presented to it, -and as such does not resolve issues that may exist in the processed HTML, -producing a literal interpretation of the input. - -If your use case requires semantically well-formed HTML, as defined by the -WHATWG specification, the parser should be used rather than the tokenizer. +This package provides both a tokenizer and a parser, which implement the +tokenization, and tokenization and tree construction stages of the WHATWG HTML +parsing specification respectively. While the tokenizer parses and normalizes +individual HTML tokens, only the parser constructs the DOM tree from the +tokenized HTML, as described in the tree construction stage of the +specification, dynamically modifying or extending the docuemnt's DOM tree. + +If your use case requires semantically well-formed HTML documents, as defined by +the WHATWG specification, the parser should be used rather than the tokenizer. + +In security contexts, if trust decisions are being made using the tokenized or +parsed content, the input must be re-serialized (for instance by using Render or +Token.String) in order for those trust decisions to hold, as the process of +tokenization or parsing may alter the content. */ package html // import "golang.org/x/net/html" From 938ff153cfff2268dc5ceb9f99755390cf4c9af4 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 18 Apr 2023 13:22:30 +0200 Subject: [PATCH 4/7] ipv4, ipv6, nettest: skip unsupported tests on wasip1 Updates golang/go#58141 Change-Id: Iec7a525633dcc93c8941c9aaaef6e54e6867a8d0 Reviewed-on: https://go-review.googlesource.com/c/net/+/485675 Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan Mills Run-TryBot: Tobias Klauser Auto-Submit: Tobias Klauser TryBot-Result: Gopher Robot --- ipv4/multicast_test.go | 6 +++--- ipv4/multicastlistener_test.go | 10 +++++----- ipv4/multicastsockopt_test.go | 4 ++-- ipv4/readwrite_test.go | 8 ++++---- ipv4/unicast_test.go | 6 +++--- ipv4/unicastsockopt_test.go | 6 +++--- ipv6/icmp_test.go | 4 ++-- ipv6/multicast_test.go | 4 ++-- ipv6/multicastlistener_test.go | 10 +++++----- ipv6/multicastsockopt_test.go | 2 +- ipv6/readwrite_test.go | 8 ++++---- ipv6/sockopt_test.go | 6 +++--- ipv6/unicast_test.go | 4 ++-- ipv6/unicastsockopt_test.go | 4 ++-- nettest/nettest.go | 8 ++++---- 15 files changed, 45 insertions(+), 45 deletions(-) diff --git a/ipv4/multicast_test.go b/ipv4/multicast_test.go index 09463bff0..fd086580d 100644 --- a/ipv4/multicast_test.go +++ b/ipv4/multicast_test.go @@ -30,7 +30,7 @@ var packetConnReadWriteMulticastUDPTests = []struct { func TestPacketConnReadWriteMulticastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "windows", "zos": + case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) @@ -132,7 +132,7 @@ var packetConnReadWriteMulticastICMPTests = []struct { func TestPacketConnReadWriteMulticastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "windows": + case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { @@ -262,7 +262,7 @@ var rawConnReadWriteMulticastICMPTests = []struct { func TestRawConnReadWriteMulticastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "windows": + case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { diff --git a/ipv4/multicastlistener_test.go b/ipv4/multicastlistener_test.go index 77bad6676..0035c26f6 100644 --- a/ipv4/multicastlistener_test.go +++ b/ipv4/multicastlistener_test.go @@ -21,7 +21,7 @@ var udpMultipleGroupListenerTests = []net.Addr{ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -61,7 +61,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -116,7 +116,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -172,7 +172,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { @@ -217,7 +217,7 @@ func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { diff --git a/ipv4/multicastsockopt_test.go b/ipv4/multicastsockopt_test.go index b0ddd0716..9339e8901 100644 --- a/ipv4/multicastsockopt_test.go +++ b/ipv4/multicastsockopt_test.go @@ -26,7 +26,7 @@ var packetConnMulticastSocketOptionTests = []struct { func TestPacketConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "zos": t.Skipf("not supported on %s", runtime.GOOS) } ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) @@ -66,7 +66,7 @@ var rawConnMulticastSocketOptionTests = []struct { func TestRawConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { diff --git a/ipv4/readwrite_test.go b/ipv4/readwrite_test.go index 27aaa7bcc..28bd22d45 100644 --- a/ipv4/readwrite_test.go +++ b/ipv4/readwrite_test.go @@ -21,7 +21,7 @@ import ( func BenchmarkReadWriteUnicast(b *testing.B) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": b.Skipf("not supported on %s", runtime.GOOS) } @@ -69,7 +69,7 @@ func BenchmarkReadWriteUnicast(b *testing.B) { func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": b.Skipf("not supported on %s", runtime.GOOS) } @@ -220,7 +220,7 @@ func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } @@ -324,7 +324,7 @@ func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } diff --git a/ipv4/unicast_test.go b/ipv4/unicast_test.go index 12bbdb41f..879f2fc05 100644 --- a/ipv4/unicast_test.go +++ b/ipv4/unicast_test.go @@ -20,7 +20,7 @@ import ( func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } // Skip this check on z/OS since net.Interfaces() does not return loopback, however @@ -85,7 +85,7 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { @@ -180,7 +180,7 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) { func TestRawConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { diff --git a/ipv4/unicastsockopt_test.go b/ipv4/unicastsockopt_test.go index 58d653eac..0cd403da2 100644 --- a/ipv4/unicastsockopt_test.go +++ b/ipv4/unicastsockopt_test.go @@ -16,7 +16,7 @@ import ( func TestConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { @@ -61,7 +61,7 @@ var packetConnUnicastSocketOptionTests = []struct { func TestPacketConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback); err != nil { @@ -86,7 +86,7 @@ func TestPacketConnUnicastSocketOptions(t *testing.T) { func TestRawConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsRawSocket() { diff --git a/ipv6/icmp_test.go b/ipv6/icmp_test.go index 3652067d8..3fe9ef4fd 100644 --- a/ipv6/icmp_test.go +++ b/ipv6/icmp_test.go @@ -34,7 +34,7 @@ func TestICMPString(t *testing.T) { func TestICMPFilter(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } @@ -61,7 +61,7 @@ func TestICMPFilter(t *testing.T) { func TestSetICMPFilter(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/multicast_test.go b/ipv6/multicast_test.go index 267098a10..0cd1ac4e3 100644 --- a/ipv6/multicast_test.go +++ b/ipv6/multicast_test.go @@ -29,7 +29,7 @@ var packetConnReadWriteMulticastUDPTests = []struct { func TestPacketConnReadWriteMulticastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -144,7 +144,7 @@ func TestPacketConnReadWriteMulticastICMP(t *testing.T) { `and needs investigation, see golang.org/issue/42064`) } switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/multicastlistener_test.go b/ipv6/multicastlistener_test.go index a4dc86342..386b38791 100644 --- a/ipv6/multicastlistener_test.go +++ b/ipv6/multicastlistener_test.go @@ -21,7 +21,7 @@ var udpMultipleGroupListenerTests = []net.Addr{ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -61,7 +61,7 @@ func TestUDPSinglePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -116,7 +116,7 @@ func TestUDPMultiplePacketConnWithMultipleGroupListeners(t *testing.T) { func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -172,7 +172,7 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { @@ -216,7 +216,7 @@ func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "darwin", "ios", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address t.Skipf("not supported on %s", runtime.GOOS) - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/multicastsockopt_test.go b/ipv6/multicastsockopt_test.go index d598d08d0..9d4de24c2 100644 --- a/ipv6/multicastsockopt_test.go +++ b/ipv6/multicastsockopt_test.go @@ -26,7 +26,7 @@ var packetConnMulticastSocketOptionTests = []struct { func TestPacketConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/readwrite_test.go b/ipv6/readwrite_test.go index 131b1904c..51c1b8bc4 100644 --- a/ipv6/readwrite_test.go +++ b/ipv6/readwrite_test.go @@ -21,7 +21,7 @@ import ( func BenchmarkReadWriteUnicast(b *testing.B) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": b.Skipf("not supported on %s", runtime.GOOS) } @@ -72,7 +72,7 @@ func BenchmarkReadWriteUnicast(b *testing.B) { func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": b.Skipf("not supported on %s", runtime.GOOS) } @@ -220,7 +220,7 @@ func BenchmarkPacketConnReadWriteUnicast(b *testing.B) { func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback) @@ -327,7 +327,7 @@ func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) { func TestPacketConnConcurrentReadWriteUnicast(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } diff --git a/ipv6/sockopt_test.go b/ipv6/sockopt_test.go index ab0d2e4e5..ad6cb46d2 100644 --- a/ipv6/sockopt_test.go +++ b/ipv6/sockopt_test.go @@ -17,7 +17,7 @@ import ( func TestConnInitiatorPathMTU(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "wasip1", "zos": t.Skipf("not supported on %s", runtime.GOOS) } @@ -51,7 +51,7 @@ func TestConnInitiatorPathMTU(t *testing.T) { func TestConnResponderPathMTU(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "wasip1", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil { @@ -84,7 +84,7 @@ func TestConnResponderPathMTU(t *testing.T) { func TestPacketConnChecksum(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/unicast_test.go b/ipv6/unicast_test.go index e03c2cd33..d5ec85eab 100644 --- a/ipv6/unicast_test.go +++ b/ipv6/unicast_test.go @@ -20,7 +20,7 @@ import ( func TestPacketConnReadWriteUnicastUDP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil { @@ -91,7 +91,7 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { func TestPacketConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows", "zos": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { diff --git a/ipv6/unicastsockopt_test.go b/ipv6/unicastsockopt_test.go index c3abe2d14..bb477ea6a 100644 --- a/ipv6/unicastsockopt_test.go +++ b/ipv6/unicastsockopt_test.go @@ -16,7 +16,7 @@ import ( func TestConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil { @@ -61,7 +61,7 @@ var packetConnUnicastSocketOptionTests = []struct { func TestPacketConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if _, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagLoopback); err != nil { diff --git a/nettest/nettest.go b/nettest/nettest.go index 1e350f09c..3656c3c54 100644 --- a/nettest/nettest.go +++ b/nettest/nettest.go @@ -103,12 +103,12 @@ func TestableNetwork(network string) bool { // This is an internal network name for testing on the // package net of the standard library. switch runtime.GOOS { - case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "windows": + case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "wasip1", "windows": return false } case "ip", "ip4", "ip6": switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9": + case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1": return false default: if os.Getuid() != 0 { @@ -117,14 +117,14 @@ func TestableNetwork(network string) bool { } case "unix", "unixgram": switch runtime.GOOS { - case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "windows": + case "android", "fuchsia", "hurd", "ios", "js", "nacl", "plan9", "wasip1", "windows": return false case "aix": return unixStrmDgramEnabled() } case "unixpacket": switch runtime.GOOS { - case "aix", "android", "fuchsia", "hurd", "darwin", "ios", "js", "nacl", "plan9", "windows", "zos": + case "aix", "android", "fuchsia", "hurd", "darwin", "ios", "js", "nacl", "plan9", "wasip1", "windows", "zos": return false } } From 0bfab66a03570232c7aaea77dcdd2355ae6e9db8 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 28 Apr 2023 17:33:01 +0200 Subject: [PATCH 5/7] ipv4, ipv6: drop redundant skip checks based on GOOS All the dropped platforms either don't support raw sockets or the tests pass sucessfully (e.g. ipv4.TestPacketConnReadWriteMulticastICMP on solaris), so the tests can rely on being skipped due to !nettest.SupportsRawSocket(). Also check for errNotImplemented to cover cases where functionality is not available on windows. Change-Id: Ic9107a7ca16e9d9faed4991e1148b493c646ea7d Reviewed-on: https://go-review.googlesource.com/c/net/+/489155 Run-TryBot: Tobias Klauser Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov Auto-Submit: Tobias Klauser --- ipv4/export_test.go | 7 +++++++ ipv4/helper_posix_test.go | 5 ++++- ipv4/multicast_test.go | 8 -------- ipv4/multicastlistener_test.go | 8 -------- ipv4/multicastsockopt_test.go | 4 ---- ipv4/unicast_test.go | 8 -------- ipv4/unicastsockopt_test.go | 4 ---- ipv6/export_test.go | 7 +++++++ ipv6/helper_posix_test.go | 5 ++++- ipv6/icmp_test.go | 10 +++++----- ipv6/multicastlistener_test.go | 6 ------ ipv6/sockopt_test.go | 9 ++++----- ipv6/unicast_test.go | 9 ++++----- 13 files changed, 35 insertions(+), 55 deletions(-) create mode 100644 ipv4/export_test.go create mode 100644 ipv6/export_test.go diff --git a/ipv4/export_test.go b/ipv4/export_test.go new file mode 100644 index 000000000..c2229e732 --- /dev/null +++ b/ipv4/export_test.go @@ -0,0 +1,7 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv4 + +var ErrNotImplemented = errNotImplemented diff --git a/ipv4/helper_posix_test.go b/ipv4/helper_posix_test.go index 40f432c51..4f6ecc0fd 100644 --- a/ipv4/helper_posix_test.go +++ b/ipv4/helper_posix_test.go @@ -8,8 +8,11 @@ package ipv4_test import ( + "errors" "os" "syscall" + + "golang.org/x/net/ipv4" ) func protocolNotSupported(err error) bool { @@ -28,5 +31,5 @@ func protocolNotSupported(err error) bool { } } } - return false + return errors.Is(err, ipv4.ErrNotImplemented) } diff --git a/ipv4/multicast_test.go b/ipv4/multicast_test.go index fd086580d..d056ff6de 100644 --- a/ipv4/multicast_test.go +++ b/ipv4/multicast_test.go @@ -131,10 +131,6 @@ var packetConnReadWriteMulticastICMPTests = []struct { } func TestPacketConnReadWriteMulticastICMP(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } @@ -261,10 +257,6 @@ var rawConnReadWriteMulticastICMPTests = []struct { } func TestRawConnReadWriteMulticastICMP(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "illumos", "js", "nacl", "plan9", "solaris", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if testing.Short() { t.Skip("to avoid external network") } diff --git a/ipv4/multicastlistener_test.go b/ipv4/multicastlistener_test.go index 0035c26f6..906964682 100644 --- a/ipv4/multicastlistener_test.go +++ b/ipv4/multicastlistener_test.go @@ -171,10 +171,6 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { } func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": - t.Skipf("not supported on %s", runtime.GOOS) - } if testing.Short() { t.Skip("to avoid external network") } @@ -216,10 +212,6 @@ func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { } func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": - t.Skipf("not supported on %s", runtime.GOOS) - } if testing.Short() { t.Skip("to avoid external network") } diff --git a/ipv4/multicastsockopt_test.go b/ipv4/multicastsockopt_test.go index 9339e8901..ddf9e6023 100644 --- a/ipv4/multicastsockopt_test.go +++ b/ipv4/multicastsockopt_test.go @@ -65,10 +65,6 @@ var rawConnMulticastSocketOptionTests = []struct { } func TestRawConnMulticastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "zos": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/ipv4/unicast_test.go b/ipv4/unicast_test.go index 879f2fc05..a68f4cc02 100644 --- a/ipv4/unicast_test.go +++ b/ipv4/unicast_test.go @@ -84,10 +84,6 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { } func TestPacketConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } @@ -179,10 +175,6 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) { } func TestRawConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/ipv4/unicastsockopt_test.go b/ipv4/unicastsockopt_test.go index 0cd403da2..837baba74 100644 --- a/ipv4/unicastsockopt_test.go +++ b/ipv4/unicastsockopt_test.go @@ -85,10 +85,6 @@ func TestPacketConnUnicastSocketOptions(t *testing.T) { } func TestRawConnUnicastSocketOptions(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsRawSocket() { t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) } diff --git a/ipv6/export_test.go b/ipv6/export_test.go new file mode 100644 index 000000000..a506cb38d --- /dev/null +++ b/ipv6/export_test.go @@ -0,0 +1,7 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +var ErrNotImplemented = errNotImplemented diff --git a/ipv6/helper_posix_test.go b/ipv6/helper_posix_test.go index ab561f34f..8ca6a3c3c 100644 --- a/ipv6/helper_posix_test.go +++ b/ipv6/helper_posix_test.go @@ -8,8 +8,11 @@ package ipv6_test import ( + "errors" "os" "syscall" + + "golang.org/x/net/ipv6" ) func protocolNotSupported(err error) bool { @@ -28,5 +31,5 @@ func protocolNotSupported(err error) bool { } } } - return false + return errors.Is(err, ipv6.ErrNotImplemented) } diff --git a/ipv6/icmp_test.go b/ipv6/icmp_test.go index 3fe9ef4fd..9d8d68127 100644 --- a/ipv6/icmp_test.go +++ b/ipv6/icmp_test.go @@ -5,6 +5,7 @@ package ipv6_test import ( + "errors" "net" "reflect" "runtime" @@ -60,10 +61,6 @@ func TestICMPFilter(t *testing.T) { } func TestSetICMPFilter(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsIPv6() { t.Skip("ipv6 is not supported") } @@ -83,9 +80,12 @@ func TestSetICMPFilter(t *testing.T) { f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoRequest) f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { + if err := p.SetICMPFilter(&f); errors.Is(err, ipv6.ErrNotImplemented) { + t.Skipf("setting ICMP filter not supported: %v", err) + } else if err != nil { t.Fatal(err) } + kf, err := p.ICMPFilter() if err != nil { t.Fatal(err) diff --git a/ipv6/multicastlistener_test.go b/ipv6/multicastlistener_test.go index 386b38791..3daa19838 100644 --- a/ipv6/multicastlistener_test.go +++ b/ipv6/multicastlistener_test.go @@ -171,10 +171,6 @@ func TestUDPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { } func TestIPSinglePacketConnWithSingleGroupListener(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsIPv6() { t.Skip("ipv6 is not supported") } @@ -216,8 +212,6 @@ func TestIPPerInterfaceSinglePacketConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "darwin", "ios", "dragonfly", "openbsd": // platforms that return fe80::1%lo0: bind: can't assign requested address t.Skipf("not supported on %s", runtime.GOOS) - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) } if !nettest.SupportsIPv6() { t.Skip("ipv6 is not supported") diff --git a/ipv6/sockopt_test.go b/ipv6/sockopt_test.go index ad6cb46d2..3dc42c139 100644 --- a/ipv6/sockopt_test.go +++ b/ipv6/sockopt_test.go @@ -5,6 +5,7 @@ package ipv6_test import ( + "errors" "fmt" "net" "runtime" @@ -83,10 +84,6 @@ func TestConnResponderPathMTU(t *testing.T) { } func TestPacketConnChecksum(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsIPv6() { t.Skip("ipv6 is not supported") } @@ -104,7 +101,9 @@ func TestPacketConnChecksum(t *testing.T) { offset := 12 // see RFC 5340 for _, toggle := range []bool{false, true} { - if err := p.SetChecksum(toggle, offset); err != nil { + if err := p.SetChecksum(toggle, offset); errors.Is(err, ipv6.ErrNotImplemented) { + t.Skipf("setting checksum not supported: %v", err) + } else if err != nil { if toggle { t.Fatalf("ipv6.PacketConn.SetChecksum(%v, %v) failed: %v", toggle, offset, err) } else { diff --git a/ipv6/unicast_test.go b/ipv6/unicast_test.go index d5ec85eab..04e5b06fa 100644 --- a/ipv6/unicast_test.go +++ b/ipv6/unicast_test.go @@ -6,6 +6,7 @@ package ipv6_test import ( "bytes" + "errors" "net" "os" "runtime" @@ -90,10 +91,6 @@ func TestPacketConnReadWriteUnicastUDP(t *testing.T) { } func TestPacketConnReadWriteUnicastICMP(t *testing.T) { - switch runtime.GOOS { - case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows", "zos": - t.Skipf("not supported on %s", runtime.GOOS) - } if !nettest.SupportsIPv6() { t.Skip("ipv6 is not supported") } @@ -128,7 +125,9 @@ func TestPacketConnReadWriteUnicastICMP(t *testing.T) { var f ipv6.ICMPFilter f.SetAll(true) f.Accept(ipv6.ICMPTypeEchoReply) - if err := p.SetICMPFilter(&f); err != nil { + if err := p.SetICMPFilter(&f); errors.Is(err, ipv6.ErrNotImplemented) { + t.Skipf("setting ICMP filter not supported: %v", err) + } else if err != nil { t.Fatal(err) } From 82780d606d189ee6d3e9dd4683e493d832f3caaf Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Tue, 18 Apr 2023 11:18:57 -0700 Subject: [PATCH 6/7] http2: don't reuse connections that are experiencing errors When a request on a connection fails to complete successfully, mark the conn as doNotReuse. It's possible for requests to fail for reasons unrelated to connection health, but opening a new connection unnecessarily is less of an impact than reusing a dead connection. Fixes golang/go#59690 Change-Id: I40bf6cefae602ead70c3bcf2fe573cc13f34a385 Reviewed-on: https://go-review.googlesource.com/c/net/+/486156 Run-TryBot: Damien Neil TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills --- http2/transport.go | 30 +++- http2/transport_test.go | 333 +++++++++++++++++++++++++--------------- 2 files changed, 234 insertions(+), 129 deletions(-) diff --git a/http2/transport.go b/http2/transport.go index f965579f7..ac90a2631 100644 --- a/http2/transport.go +++ b/http2/transport.go @@ -1266,6 +1266,27 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { return res, nil } + cancelRequest := func(cs *clientStream, err error) error { + cs.cc.mu.Lock() + defer cs.cc.mu.Unlock() + cs.abortStreamLocked(err) + if cs.ID != 0 { + // This request may have failed because of a problem with the connection, + // or for some unrelated reason. (For example, the user might have canceled + // the request without waiting for a response.) Mark the connection as + // not reusable, since trying to reuse a dead connection is worse than + // unnecessarily creating a new one. + // + // If cs.ID is 0, then the request was never allocated a stream ID and + // whatever went wrong was unrelated to the connection. We might have + // timed out waiting for a stream slot when StrictMaxConcurrentStreams + // is set, for example, in which case retrying on a different connection + // will not help. + cs.cc.doNotReuse = true + } + return err + } + for { select { case <-cs.respHeaderRecv: @@ -1280,15 +1301,12 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) { return handleResponseHeaders() default: waitDone() - return nil, cs.abortErr + return nil, cancelRequest(cs, cs.abortErr) } case <-ctx.Done(): - err := ctx.Err() - cs.abortStream(err) - return nil, err + return nil, cancelRequest(cs, ctx.Err()) case <-cs.reqCancel: - cs.abortStream(errRequestCanceled) - return nil, errRequestCanceled + return nil, cancelRequest(cs, errRequestCanceled) } } } diff --git a/http2/transport_test.go b/http2/transport_test.go index 5adef4292..54d455148 100644 --- a/http2/transport_test.go +++ b/http2/transport_test.go @@ -775,7 +775,6 @@ func newClientTester(t *testing.T) *clientTester { cc, err := net.Dial("tcp", ln.Addr().String()) if err != nil { t.Fatal(err) - } sc, err := ln.Accept() if err != nil { @@ -1765,6 +1764,18 @@ func TestTransportChecksRequestHeaderListSize(t *testing.T) { defer tr.CloseIdleConnections() checkRoundTrip := func(req *http.Request, wantErr error, desc string) { + // Make an arbitrary request to ensure we get the server's + // settings frame and initialize peerMaxHeaderListSize. + req0, err := http.NewRequest("GET", st.ts.URL, nil) + if err != nil { + t.Fatalf("newRequest: NewRequest: %v", err) + } + res0, err := tr.RoundTrip(req0) + if err != nil { + t.Errorf("%v: Initial RoundTrip err = %v", desc, err) + } + res0.Body.Close() + res, err := tr.RoundTrip(req) if err != wantErr { if res != nil { @@ -1825,13 +1836,9 @@ func TestTransportChecksRequestHeaderListSize(t *testing.T) { return req } - // Make an arbitrary request to ensure we get the server's - // settings frame and initialize peerMaxHeaderListSize. + // Validate peerMaxHeaderListSize. req := newRequest() checkRoundTrip(req, nil, "Initial request") - - // Get the ClientConn associated with the request and validate - // peerMaxHeaderListSize. addr := authorityAddr(req.URL.Scheme, req.URL.Host) cc, err := tr.connPool().GetClientConn(req, addr) if err != nil { @@ -3738,35 +3745,33 @@ func testTransportPingWhenReading(t *testing.T, readIdleTimeout, deadline time.D ct.run() } -func TestTransportRetryAfterGOAWAY(t *testing.T) { - var dialer struct { - sync.Mutex - count int - } - ct1 := make(chan *clientTester) - ct2 := make(chan *clientTester) - +func testClientMultipleDials(t *testing.T, client func(*Transport), server func(int, *clientTester)) { ln := newLocalListener(t) defer ln.Close() + var ( + mu sync.Mutex + count int + conns []net.Conn + ) + var wg sync.WaitGroup tr := &Transport{ TLSClientConfig: tlsConfigInsecure, } tr.DialTLS = func(network, addr string, cfg *tls.Config) (net.Conn, error) { - dialer.Lock() - defer dialer.Unlock() - dialer.count++ - if dialer.count == 3 { - return nil, errors.New("unexpected number of dials") - } + mu.Lock() + defer mu.Unlock() + count++ cc, err := net.Dial("tcp", ln.Addr().String()) if err != nil { return nil, fmt.Errorf("dial error: %v", err) } + conns = append(conns, cc) sc, err := ln.Accept() if err != nil { return nil, fmt.Errorf("accept error: %v", err) } + conns = append(conns, sc) ct := &clientTester{ t: t, tr: tr, @@ -3774,19 +3779,26 @@ func TestTransportRetryAfterGOAWAY(t *testing.T) { sc: sc, fr: NewFramer(sc, sc), } - switch dialer.count { - case 1: - ct1 <- ct - case 2: - ct2 <- ct - } + wg.Add(1) + go func(count int) { + defer wg.Done() + server(count, ct) + sc.Close() + }(count) return cc, nil } - errs := make(chan error, 3) + client(tr) + tr.CloseIdleConnections() + ln.Close() + for _, c := range conns { + c.Close() + } + wg.Wait() +} - // Client. - go func() { +func TestTransportRetryAfterGOAWAY(t *testing.T) { + client := func(tr *Transport) { req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) res, err := tr.RoundTrip(req) if res != nil { @@ -3796,102 +3808,76 @@ func TestTransportRetryAfterGOAWAY(t *testing.T) { } } if err != nil { - err = fmt.Errorf("RoundTrip: %v", err) - } - errs <- err - }() - - connToClose := make(chan io.Closer, 2) - - // Server for the first request. - go func() { - ct := <-ct1 - - connToClose <- ct.cc - ct.greet() - hf, err := ct.firstHeaders() - if err != nil { - errs <- fmt.Errorf("server1 failed reading HEADERS: %v", err) - return + t.Errorf("RoundTrip: %v", err) } - t.Logf("server1 got %v", hf) - if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil { - errs <- fmt.Errorf("server1 failed writing GOAWAY: %v", err) - return - } - errs <- nil - }() + } - // Server for the second request. - go func() { - ct := <-ct2 + server := func(count int, ct *clientTester) { + switch count { + case 1: + ct.greet() + hf, err := ct.firstHeaders() + if err != nil { + t.Errorf("server1 failed reading HEADERS: %v", err) + return + } + t.Logf("server1 got %v", hf) + if err := ct.fr.WriteGoAway(0 /*max id*/, ErrCodeNo, nil); err != nil { + t.Errorf("server1 failed writing GOAWAY: %v", err) + return + } + case 2: + ct.greet() + hf, err := ct.firstHeaders() + if err != nil { + t.Errorf("server2 failed reading HEADERS: %v", err) + return + } + t.Logf("server2 got %v", hf) - connToClose <- ct.cc - ct.greet() - hf, err := ct.firstHeaders() - if err != nil { - errs <- fmt.Errorf("server2 failed reading HEADERS: %v", err) + var buf bytes.Buffer + enc := hpack.NewEncoder(&buf) + enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) + enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) + err = ct.fr.WriteHeaders(HeadersFrameParam{ + StreamID: hf.StreamID, + EndHeaders: true, + EndStream: false, + BlockFragment: buf.Bytes(), + }) + if err != nil { + t.Errorf("server2 failed writing response HEADERS: %v", err) + } + default: + t.Errorf("unexpected number of dials") return } - t.Logf("server2 got %v", hf) - - var buf bytes.Buffer - enc := hpack.NewEncoder(&buf) - enc.WriteField(hpack.HeaderField{Name: ":status", Value: "200"}) - enc.WriteField(hpack.HeaderField{Name: "foo", Value: "bar"}) - err = ct.fr.WriteHeaders(HeadersFrameParam{ - StreamID: hf.StreamID, - EndHeaders: true, - EndStream: false, - BlockFragment: buf.Bytes(), - }) - if err != nil { - errs <- fmt.Errorf("server2 failed writing response HEADERS: %v", err) - } else { - errs <- nil - } - }() - - for k := 0; k < 3; k++ { - err := <-errs - if err != nil { - t.Error(err) - } } - close(connToClose) - for c := range connToClose { - c.Close() - } + testClientMultipleDials(t, client, server) } func TestTransportRetryAfterRefusedStream(t *testing.T) { clientDone := make(chan struct{}) - ct := newClientTester(t) - ct.client = func() error { - defer ct.cc.(*net.TCPConn).CloseWrite() - if runtime.GOOS == "plan9" { - // CloseWrite not supported on Plan 9; Issue 17906 - defer ct.cc.(*net.TCPConn).Close() - } + client := func(tr *Transport) { defer close(clientDone) req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) - resp, err := ct.tr.RoundTrip(req) + resp, err := tr.RoundTrip(req) if err != nil { - return fmt.Errorf("RoundTrip: %v", err) + t.Errorf("RoundTrip: %v", err) + return } resp.Body.Close() if resp.StatusCode != 204 { - return fmt.Errorf("Status = %v; want 204", resp.StatusCode) + t.Errorf("Status = %v; want 204", resp.StatusCode) + return } - return nil } - ct.server = func() error { + + server := func(count int, ct *clientTester) { ct.greet() var buf bytes.Buffer enc := hpack.NewEncoder(&buf) - nreq := 0 - for { f, err := ct.fr.ReadFrame() if err != nil { @@ -3900,19 +3886,19 @@ func TestTransportRetryAfterRefusedStream(t *testing.T) { // If the client's done, it // will have reported any // errors on its side. - return nil default: - return err + t.Error(err) } + return } switch f := f.(type) { case *WindowUpdateFrame, *SettingsFrame: case *HeadersFrame: if !f.HeadersEnded() { - return fmt.Errorf("headers should have END_HEADERS be ended: %v", f) + t.Errorf("headers should have END_HEADERS be ended: %v", f) + return } - nreq++ - if nreq == 1 { + if count == 1 { ct.fr.WriteRSTStream(f.StreamID, ErrCodeRefusedStream) } else { enc.WriteField(hpack.HeaderField{Name: ":status", Value: "204"}) @@ -3924,11 +3910,13 @@ func TestTransportRetryAfterRefusedStream(t *testing.T) { }) } default: - return fmt.Errorf("Unexpected client frame %v", f) + t.Errorf("Unexpected client frame %v", f) + return } } } - ct.run() + + testClientMultipleDials(t, client, server) } func TestTransportRetryHasLimit(t *testing.T) { @@ -4143,6 +4131,7 @@ func TestTransportRequestsStallAtServerLimit(t *testing.T) { greet := make(chan struct{}) // server sends initial SETTINGS frame gotRequest := make(chan struct{}) // server received a request clientDone := make(chan struct{}) + cancelClientRequest := make(chan struct{}) // Collect errors from goroutines. var wg sync.WaitGroup @@ -4221,9 +4210,8 @@ func TestTransportRequestsStallAtServerLimit(t *testing.T) { req, _ := http.NewRequest("GET", fmt.Sprintf("https://dummy.tld/%d", k), body) if k == maxConcurrent { // This request will be canceled. - cancel := make(chan struct{}) - req.Cancel = cancel - close(cancel) + req.Cancel = cancelClientRequest + close(cancelClientRequest) _, err := ct.tr.RoundTrip(req) close(clientRequestCancelled) if err == nil { @@ -5986,14 +5974,21 @@ func TestTransportRetriesOnStreamProtocolError(t *testing.T) { } func TestClientConnReservations(t *testing.T) { - cc := &ClientConn{ - reqHeaderMu: make(chan struct{}, 1), - streams: make(map[uint32]*clientStream), - maxConcurrentStreams: initialMaxConcurrentStreams, - nextStreamID: 1, - t: &Transport{}, + st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { + }, func(s *Server) { + s.MaxConcurrentStreams = initialMaxConcurrentStreams + }) + defer st.Close() + + tr := &Transport{TLSClientConfig: tlsConfigInsecure} + defer tr.CloseIdleConnections() + + cc, err := tr.newClientConn(st.cc, false) + if err != nil { + t.Fatal(err) } - cc.cond = sync.NewCond(&cc.mu) + + req, _ := http.NewRequest("GET", st.ts.URL, nil) n := 0 for n <= initialMaxConcurrentStreams && cc.ReserveNewRequest() { n++ @@ -6001,8 +5996,8 @@ func TestClientConnReservations(t *testing.T) { if n != initialMaxConcurrentStreams { t.Errorf("did %v reservations; want %v", n, initialMaxConcurrentStreams) } - if _, err := cc.RoundTrip(new(http.Request)); !errors.Is(err, errNilRequestURL) { - t.Fatalf("RoundTrip error = %v; want errNilRequestURL", err) + if _, err := cc.RoundTrip(req); err != nil { + t.Fatalf("RoundTrip error = %v", err) } n2 := 0 for n2 <= 5 && cc.ReserveNewRequest() { @@ -6014,7 +6009,7 @@ func TestClientConnReservations(t *testing.T) { // Use up all the reservations for i := 0; i < n; i++ { - cc.RoundTrip(new(http.Request)) + cc.RoundTrip(req) } n2 = 0 @@ -6370,3 +6365,95 @@ func TestTransportSlowClose(t *testing.T) { } res.Body.Close() } + +type blockReadConn struct { + net.Conn + blockc chan struct{} +} + +func (c *blockReadConn) Read(b []byte) (n int, err error) { + <-c.blockc + return c.Conn.Read(b) +} + +func TestTransportReuseAfterError(t *testing.T) { + serverReqc := make(chan struct{}, 3) + st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) { + serverReqc <- struct{}{} + }, optOnlyServer) + defer st.Close() + + var ( + unblockOnce sync.Once + blockc = make(chan struct{}) + connCountMu sync.Mutex + connCount int + ) + tr := &Transport{ + TLSClientConfig: tlsConfigInsecure, + DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { + // The first connection dialed will block on reads until blockc is closed. + connCountMu.Lock() + defer connCountMu.Unlock() + connCount++ + conn, err := tls.Dial(network, addr, cfg) + if err != nil { + return nil, err + } + if connCount == 1 { + return &blockReadConn{ + Conn: conn, + blockc: blockc, + }, nil + } + return conn, nil + }, + } + defer tr.CloseIdleConnections() + defer unblockOnce.Do(func() { + // Ensure that reads on blockc are unblocked if we return early. + close(blockc) + }) + + req, _ := http.NewRequest("GET", st.ts.URL, nil) + + // Request 1 is made on conn 1. + // Reading the response will block. + // Wait until the server receives the request, and continue. + req1c := make(chan struct{}) + go func() { + defer close(req1c) + res1, err := tr.RoundTrip(req.Clone(context.Background())) + if err != nil { + t.Errorf("request 1: %v", err) + } else { + res1.Body.Close() + } + }() + <-serverReqc + + // Request 2 is also made on conn 1. + // Reading the response will block. + // The request fails when the context deadline expires. + // Conn 1 should now be flagged as unfit for reuse. + timeoutCtx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond) + defer cancel() + _, err := tr.RoundTrip(req.Clone(timeoutCtx)) + if err == nil { + t.Errorf("request 2 unexpectedly succeeded (want timeout)") + } + time.Sleep(1 * time.Millisecond) + + // Request 3 is made on a new conn, and succeeds. + res3, err := tr.RoundTrip(req.Clone(context.Background())) + if err != nil { + t.Fatalf("request 3: %v", err) + } + res3.Body.Close() + + // Unblock conn 1, and verify that request 1 completes. + unblockOnce.Do(func() { + close(blockc) + }) + <-req1c +} From daac0cec0cf964a628a29bb4b82940c225b921ed Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Thu, 4 May 2023 15:52:00 +0000 Subject: [PATCH 7/7] go.mod: update golang.org/x dependencies Update golang.org/x dependencies to their latest tagged versions. Once this CL is submitted, and post-submit testing succeeds on all first-class ports across all supported Go versions, this repository will be tagged with its next minor version. Change-Id: Iadb0b7c874b69c87b0238f5011a4cc5ea86c721c Reviewed-on: https://go-review.googlesource.com/c/net/+/492637 Reviewed-by: Dmitri Shuralyov Run-TryBot: Gopher Robot TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Auto-Submit: Gopher Robot Reviewed-by: Dmitri Shuralyov --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d906d9981..f661af405 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module golang.org/x/net go 1.17 require ( - golang.org/x/sys v0.7.0 - golang.org/x/term v0.7.0 + golang.org/x/sys v0.8.0 + golang.org/x/term v0.8.0 golang.org/x/text v0.9.0 ) diff --git a/go.sum b/go.sum index 417972785..6408b66ea 100644 --- a/go.sum +++ b/go.sum @@ -16,13 +16,13 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=