diff options
Diffstat (limited to 'libgo/go/net')
-rw-r--r-- | libgo/go/net/dnsclient_unix.go | 6 | ||||
-rw-r--r-- | libgo/go/net/dnsclient_unix_test.go | 2 | ||||
-rw-r--r-- | libgo/go/net/http/transport.go | 6 | ||||
-rw-r--r-- | libgo/go/net/http/transport_internal_test.go | 9 | ||||
-rw-r--r-- | libgo/go/net/lookup_test.go | 69 | ||||
-rw-r--r-- | libgo/go/net/net_test.go | 64 | ||||
-rw-r--r-- | libgo/go/net/netip/netip.go | 2 | ||||
-rw-r--r-- | libgo/go/net/smtp/auth.go | 3 | ||||
-rw-r--r-- | libgo/go/net/udpsock_test.go | 9 |
9 files changed, 119 insertions, 51 deletions
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go index 3278791e..ad121a6 100644 --- a/libgo/go/net/dnsclient_unix.go +++ b/libgo/go/net/dnsclient_unix.go @@ -30,6 +30,10 @@ const ( // to be used as a useTCP parameter to exchange useTCPOnly = true useUDPOrTCP = false + + // Maximum DNS packet size. + // Value taken from https://dnsflagday.net/2020/. + maxDNSPacketSize = 1232 ) var ( @@ -82,7 +86,7 @@ func dnsPacketRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte) return dnsmessage.Parser{}, dnsmessage.Header{}, err } - b = make([]byte, 512) // see RFC 1035 + b = make([]byte, maxDNSPacketSize) for { n, err := c.Read(b) if err != nil { diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go index e34c0a5..0ea2fae 100644 --- a/libgo/go/net/dnsclient_unix_test.go +++ b/libgo/go/net/dnsclient_unix_test.go @@ -881,7 +881,7 @@ func (f *fakeDNSPacketConn) Close() error { func TestIgnoreDNSForgeries(t *testing.T) { c, s := Pipe() go func() { - b := make([]byte, 512) + b := make([]byte, maxDNSPacketSize) n, err := s.Read(b) if err != nil { t.Error(err) diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go index 5fe3e6e..e41b20a 100644 --- a/libgo/go/net/http/transport.go +++ b/libgo/go/net/http/transport.go @@ -606,6 +606,9 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) { } else if !pconn.shouldRetryRequest(req, err) { // Issue 16465: return underlying net.Conn.Read error from peek, // as we've historically done. + if e, ok := err.(nothingWrittenError); ok { + err = e.error + } if e, ok := err.(transportReadFromServerError); ok { err = e.err } @@ -2032,6 +2035,9 @@ func (pc *persistConn) mapRoundTripError(req *transportRequest, startBytesWritte } if _, ok := err.(transportReadFromServerError); ok { + if pc.nwrite == startBytesWritten { + return nothingWrittenError{err} + } // Don't decorate return err } diff --git a/libgo/go/net/http/transport_internal_test.go b/libgo/go/net/http/transport_internal_test.go index 1cce272..2ed637e 100644 --- a/libgo/go/net/http/transport_internal_test.go +++ b/libgo/go/net/http/transport_internal_test.go @@ -52,8 +52,8 @@ func TestTransportPersistConnReadLoopEOF(t *testing.T) { conn.Close() // simulate the server hanging up on the client _, err = pc.roundTrip(treq) - if !isTransportReadFromServerError(err) && err != errServerClosedIdle { - t.Errorf("roundTrip = %#v, %v; want errServerClosedIdle or transportReadFromServerError", err, err) + if !isNothingWrittenError(err) && !isTransportReadFromServerError(err) && err != errServerClosedIdle { + t.Errorf("roundTrip = %#v, %v; want errServerClosedIdle, transportReadFromServerError, or nothingWrittenError", err, err) } <-pc.closech @@ -63,6 +63,11 @@ func TestTransportPersistConnReadLoopEOF(t *testing.T) { } } +func isNothingWrittenError(err error) bool { + _, ok := err.(nothingWrittenError) + return ok +} + func isTransportReadFromServerError(err error) bool { _, ok := err.(transportReadFromServerError) return ok diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go index 063d650..3a31f56 100644 --- a/libgo/go/net/lookup_test.go +++ b/libgo/go/net/lookup_test.go @@ -883,21 +883,66 @@ func TestLookupNonLDH(t *testing.T) { func TestLookupContextCancel(t *testing.T) { mustHaveExternalNetwork(t) - defer dnsWaitGroup.Wait() + testenv.SkipFlakyNet(t) - ctx, ctxCancel := context.WithCancel(context.Background()) - ctxCancel() - _, err := DefaultResolver.LookupIPAddr(ctx, "google.com") - if err.(*DNSError).Err != errCanceled.Error() { - testenv.SkipFlakyNet(t) - t.Fatal(err) + origTestHookLookupIP := testHookLookupIP + defer func() { + dnsWaitGroup.Wait() + testHookLookupIP = origTestHookLookupIP + }() + + lookupCtx, cancelLookup := context.WithCancel(context.Background()) + unblockLookup := make(chan struct{}) + + // Set testHookLookupIP to start a new, concurrent call to LookupIPAddr + // and cancel the original one, then block until the canceled call has returned + // (ensuring that it has performed any synchronous cleanup). + testHookLookupIP = func( + ctx context.Context, + fn func(context.Context, string, string) ([]IPAddr, error), + network string, + host string, + ) ([]IPAddr, error) { + select { + case <-unblockLookup: + default: + // Start a concurrent LookupIPAddr for the same host while the caller is + // still blocked, and sleep a little to give it time to be deduplicated + // before we cancel (and unblock) the caller. + // (If the timing doesn't quite work out, we'll end up testing sequential + // calls instead of concurrent ones, but the test should still pass.) + t.Logf("starting concurrent LookupIPAddr") + dnsWaitGroup.Add(1) + go func() { + defer dnsWaitGroup.Done() + _, err := DefaultResolver.LookupIPAddr(context.Background(), host) + if err != nil { + t.Error(err) + } + }() + time.Sleep(1 * time.Millisecond) + } + + cancelLookup() + <-unblockLookup + // If the concurrent lookup above is deduplicated to this one + // (as we expect to happen most of the time), it is important + // that the original call does not cancel the shared Context. + // (See https://go.dev/issue/22724.) Explicitly check for + // cancellation now, just in case fn itself doesn't notice it. + if err := ctx.Err(); err != nil { + t.Logf("testHookLookupIP canceled") + return nil, err + } + t.Logf("testHookLookupIP performing lookup") + return fn(ctx, network, host) } - ctx = context.Background() - _, err = DefaultResolver.LookupIPAddr(ctx, "google.com") - if err != nil { - testenv.SkipFlakyNet(t) - t.Fatal(err) + + _, err := DefaultResolver.LookupIPAddr(lookupCtx, "google.com") + if dnsErr, ok := err.(*DNSError); !ok || dnsErr.Err != errCanceled.Error() { + t.Errorf("unexpected error from canceled, blocked LookupIPAddr: %v", err) } + close(unblockLookup) } // Issue 24330: treat the nil *Resolver like a zero value. Verify nothing diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go index 7b16991..76a9c8b 100644 --- a/libgo/go/net/net_test.go +++ b/libgo/go/net/net_test.go @@ -9,7 +9,6 @@ package net import ( "errors" "fmt" - "internal/testenv" "io" "net/internal/socktest" "os" @@ -515,35 +514,50 @@ func TestCloseUnblocksRead(t *testing.T) { // Issue 24808: verify that ECONNRESET is not temporary for read. func TestNotTemporaryRead(t *testing.T) { - if runtime.GOOS == "freebsd" { - testenv.SkipFlaky(t, 25289) - } - if runtime.GOOS == "aix" { - testenv.SkipFlaky(t, 29685) - } t.Parallel() - server := func(cs *TCPConn) error { - cs.SetLinger(0) - // Give the client time to get stuck in a Read. - time.Sleep(50 * time.Millisecond) + + ln := newLocalListener(t, "tcp") + serverDone := make(chan struct{}) + dialed := make(chan struct{}) + go func() { + defer close(serverDone) + + cs, err := ln.Accept() + if err != nil { + return + } + <-dialed + cs.(*TCPConn).SetLinger(0) cs.Close() - return nil + + ln.Close() + }() + defer func() { <-serverDone }() + + ss, err := Dial("tcp", ln.Addr().String()) + if err != nil { + t.Fatal(err) } - client := func(ss *TCPConn) error { - _, err := ss.Read([]byte{0}) - if err == nil { - return errors.New("Read succeeded unexpectedly") - } else if err == io.EOF { - // This happens on Plan 9. - return nil - } else if ne, ok := err.(Error); !ok { - return fmt.Errorf("unexpected error %v", err) - } else if ne.Temporary() { - return fmt.Errorf("unexpected temporary error %v", err) + defer ss.Close() + close(dialed) + _, err = ss.Read([]byte{0}) + if err == nil { + t.Fatal("Read succeeded unexpectedly") + } else if err == io.EOF { + // This happens on Plan 9, but for some reason (prior to CL 385314) it was + // accepted everywhere else too. + if runtime.GOOS == "plan9" { + return } - return nil + // TODO: during an open development cycle, try making this a failure + // and see whether it causes the test to become flaky anywhere else. + return + } + if ne, ok := err.(Error); !ok { + t.Errorf("Read error does not implement net.Error: %v", err) + } else if ne.Temporary() { + t.Errorf("Read error is unexpectedly temporary: %v", err) } - withTCPConnPair(t, client, server) } // The various errors should implement the Error interface. diff --git a/libgo/go/net/netip/netip.go b/libgo/go/net/netip/netip.go index 591d38a..f27984a 100644 --- a/libgo/go/net/netip/netip.go +++ b/libgo/go/net/netip/netip.go @@ -1288,7 +1288,7 @@ func (p Prefix) isZero() bool { return p == Prefix{} } func (p Prefix) IsSingleIP() bool { return p.bits != 0 && int(p.bits) == p.ip.BitLen() } // ParsePrefix parses s as an IP address prefix. -// The string can be in the form "192.168.1.0/24" or "2001::db8::/32", +// The string can be in the form "192.168.1.0/24" or "2001:db8::/32", // the CIDR notation defined in RFC 4632 and RFC 4291. // // Note that masked address bits are not zeroed. Use Masked for that. diff --git a/libgo/go/net/smtp/auth.go b/libgo/go/net/smtp/auth.go index fd1a472..7a32ef6 100644 --- a/libgo/go/net/smtp/auth.go +++ b/libgo/go/net/smtp/auth.go @@ -16,8 +16,7 @@ type Auth interface { // Start begins an authentication with a server. // It returns the name of the authentication protocol // and optionally data to include in the initial AUTH message - // sent to the server. It can return proto == "" to indicate - // that the authentication should be skipped. + // sent to the server. // If it returns a non-nil error, the SMTP client aborts // the authentication attempt and closes the connection. Start(server *ServerInfo) (proto string, toServer []byte, err error) diff --git a/libgo/go/net/udpsock_test.go b/libgo/go/net/udpsock_test.go index 21f5af5..df1f7d1 100644 --- a/libgo/go/net/udpsock_test.go +++ b/libgo/go/net/udpsock_test.go @@ -415,19 +415,14 @@ func TestUDPReadSizeError(t *testing.T) { if n != len(b1) { t.Errorf("got %d; want %d", n, len(b1)) } - c1.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) b2 := make([]byte, len(b1)-1) if genericRead { n, err = c1.(Conn).Read(b2) } else { n, _, err = c1.ReadFrom(b2) } - switch err { - case nil: // ReadFrom succeeds - default: // Read may timeout, it depends on the platform - if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE - t.Fatal(err) - } + if err != nil && runtime.GOOS != "windows" { // Windows returns WSAEMSGSIZE + t.Fatal(err) } if n != len(b1)-1 { t.Fatalf("got %d; want %d", n, len(b1)-1) |