1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build !js
6
7package net
8
9import (
10	"bufio"
11	"context"
12	"internal/poll"
13	"internal/testenv"
14	"io"
15	"os"
16	"runtime"
17	"strings"
18	"sync"
19	"testing"
20	"time"
21)
22
23var prohibitionaryDialArgTests = []struct {
24	network string
25	address string
26}{
27	{"tcp6", "127.0.0.1"},
28	{"tcp6", "::ffff:127.0.0.1"},
29}
30
31func TestProhibitionaryDialArg(t *testing.T) {
32	testenv.MustHaveExternalNetwork(t)
33
34	switch runtime.GOOS {
35	case "plan9":
36		t.Skipf("not supported on %s", runtime.GOOS)
37	}
38	if !supportsIPv4map() {
39		t.Skip("mapping ipv4 address inside ipv6 address not supported")
40	}
41
42	ln, err := Listen("tcp", "[::]:0")
43	if err != nil {
44		t.Fatal(err)
45	}
46	defer ln.Close()
47
48	_, port, err := SplitHostPort(ln.Addr().String())
49	if err != nil {
50		t.Fatal(err)
51	}
52
53	for i, tt := range prohibitionaryDialArgTests {
54		c, err := Dial(tt.network, JoinHostPort(tt.address, port))
55		if err == nil {
56			c.Close()
57			t.Errorf("#%d: %v", i, err)
58		}
59	}
60}
61
62func TestDialLocal(t *testing.T) {
63	ln, err := newLocalListener("tcp")
64	if err != nil {
65		t.Fatal(err)
66	}
67	defer ln.Close()
68	_, port, err := SplitHostPort(ln.Addr().String())
69	if err != nil {
70		t.Fatal(err)
71	}
72	c, err := Dial("tcp", JoinHostPort("", port))
73	if err != nil {
74		t.Fatal(err)
75	}
76	c.Close()
77}
78
79func TestDialerDualStackFDLeak(t *testing.T) {
80	switch runtime.GOOS {
81	case "plan9":
82		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
83	case "windows":
84		t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS)
85	case "openbsd":
86		testenv.SkipFlaky(t, 15157)
87	}
88	if !supportsIPv4() || !supportsIPv6() {
89		t.Skip("both IPv4 and IPv6 are required")
90	}
91
92	before := sw.Sockets()
93	origTestHookLookupIP := testHookLookupIP
94	defer func() { testHookLookupIP = origTestHookLookupIP }()
95	testHookLookupIP = lookupLocalhost
96	handler := func(dss *dualStackServer, ln Listener) {
97		for {
98			c, err := ln.Accept()
99			if err != nil {
100				return
101			}
102			c.Close()
103		}
104	}
105	dss, err := newDualStackServer()
106	if err != nil {
107		t.Fatal(err)
108	}
109	if err := dss.buildup(handler); err != nil {
110		dss.teardown()
111		t.Fatal(err)
112	}
113
114	const N = 10
115	var wg sync.WaitGroup
116	wg.Add(N)
117	d := &Dialer{DualStack: true, Timeout: 5 * time.Second}
118	for i := 0; i < N; i++ {
119		go func() {
120			defer wg.Done()
121			c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port))
122			if err != nil {
123				t.Error(err)
124				return
125			}
126			c.Close()
127		}()
128	}
129	wg.Wait()
130	dss.teardown()
131	after := sw.Sockets()
132	if len(after) != len(before) {
133		t.Errorf("got %d; want %d", len(after), len(before))
134	}
135}
136
137// Define a pair of blackholed (IPv4, IPv6) addresses, for which dialTCP is
138// expected to hang until the timeout elapses. These addresses are reserved
139// for benchmarking by RFC 6890.
140const (
141	slowDst4 = "198.18.0.254"
142	slowDst6 = "2001:2::254"
143)
144
145// In some environments, the slow IPs may be explicitly unreachable, and fail
146// more quickly than expected. This test hook prevents dialTCP from returning
147// before the deadline.
148func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*TCPConn, error) {
149	sd := &sysDialer{network: network, address: raddr.String()}
150	c, err := sd.doDialTCP(ctx, laddr, raddr)
151	if ParseIP(slowDst4).Equal(raddr.IP) || ParseIP(slowDst6).Equal(raddr.IP) {
152		// Wait for the deadline, or indefinitely if none exists.
153		<-ctx.Done()
154	}
155	return c, err
156}
157
158func dialClosedPort(t *testing.T) (actual, expected time.Duration) {
159	// Estimate the expected time for this platform.
160	// On Windows, dialing a closed port takes roughly 1 second,
161	// but other platforms should be instantaneous.
162	if runtime.GOOS == "windows" {
163		expected = 1500 * time.Millisecond
164	} else if runtime.GOOS == "darwin" {
165		expected = 150 * time.Millisecond
166	} else {
167		expected = 95 * time.Millisecond
168	}
169
170	l, err := Listen("tcp", "127.0.0.1:0")
171	if err != nil {
172		t.Logf("dialClosedPort: Listen failed: %v", err)
173		return 999 * time.Hour, expected
174	}
175	addr := l.Addr().String()
176	l.Close()
177	// On OpenBSD, interference from TestTCPSelfConnect is mysteriously
178	// causing the first attempt to hang for a few seconds, so we throw
179	// away the first result and keep the second.
180	for i := 1; ; i++ {
181		startTime := time.Now()
182		c, err := Dial("tcp", addr)
183		if err == nil {
184			c.Close()
185		}
186		elapsed := time.Now().Sub(startTime)
187		if i == 2 {
188			t.Logf("dialClosedPort: measured delay %v", elapsed)
189			return elapsed, expected
190		}
191	}
192}
193
194func TestDialParallel(t *testing.T) {
195	testenv.MustHaveExternalNetwork(t)
196
197	if !supportsIPv4() || !supportsIPv6() {
198		t.Skip("both IPv4 and IPv6 are required")
199	}
200
201	closedPortDelay, expectClosedPortDelay := dialClosedPort(t)
202	if closedPortDelay > expectClosedPortDelay {
203		t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
204	}
205
206	const instant time.Duration = 0
207	const fallbackDelay = 200 * time.Millisecond
208
209	// Some cases will run quickly when "connection refused" is fast,
210	// or trigger the fallbackDelay on Windows. This value holds the
211	// lesser of the two delays.
212	var closedPortOrFallbackDelay time.Duration
213	if closedPortDelay < fallbackDelay {
214		closedPortOrFallbackDelay = closedPortDelay
215	} else {
216		closedPortOrFallbackDelay = fallbackDelay
217	}
218
219	origTestHookDialTCP := testHookDialTCP
220	defer func() { testHookDialTCP = origTestHookDialTCP }()
221	testHookDialTCP = slowDialTCP
222
223	nCopies := func(s string, n int) []string {
224		out := make([]string, n)
225		for i := 0; i < n; i++ {
226			out[i] = s
227		}
228		return out
229	}
230
231	var testCases = []struct {
232		primaries       []string
233		fallbacks       []string
234		teardownNetwork string
235		expectOk        bool
236		expectElapsed   time.Duration
237	}{
238		// These should just work on the first try.
239		{[]string{"127.0.0.1"}, []string{}, "", true, instant},
240		{[]string{"::1"}, []string{}, "", true, instant},
241		{[]string{"127.0.0.1", "::1"}, []string{slowDst6}, "tcp6", true, instant},
242		{[]string{"::1", "127.0.0.1"}, []string{slowDst4}, "tcp4", true, instant},
243		// Primary is slow; fallback should kick in.
244		{[]string{slowDst4}, []string{"::1"}, "", true, fallbackDelay},
245		// Skip a "connection refused" in the primary thread.
246		{[]string{"127.0.0.1", "::1"}, []string{}, "tcp4", true, closedPortDelay},
247		{[]string{"::1", "127.0.0.1"}, []string{}, "tcp6", true, closedPortDelay},
248		// Skip a "connection refused" in the fallback thread.
249		{[]string{slowDst4, slowDst6}, []string{"::1", "127.0.0.1"}, "tcp6", true, fallbackDelay + closedPortDelay},
250		// Primary refused, fallback without delay.
251		{[]string{"127.0.0.1"}, []string{"::1"}, "tcp4", true, closedPortOrFallbackDelay},
252		{[]string{"::1"}, []string{"127.0.0.1"}, "tcp6", true, closedPortOrFallbackDelay},
253		// Everything is refused.
254		{[]string{"127.0.0.1"}, []string{}, "tcp4", false, closedPortDelay},
255		// Nothing to do; fail instantly.
256		{[]string{}, []string{}, "", false, instant},
257		// Connecting to tons of addresses should not trip the deadline.
258		{nCopies("::1", 1000), []string{}, "", true, instant},
259	}
260
261	handler := func(dss *dualStackServer, ln Listener) {
262		for {
263			c, err := ln.Accept()
264			if err != nil {
265				return
266			}
267			c.Close()
268		}
269	}
270
271	// Convert a list of IP strings into TCPAddrs.
272	makeAddrs := func(ips []string, port string) addrList {
273		var out addrList
274		for _, ip := range ips {
275			addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, port))
276			if err != nil {
277				t.Fatal(err)
278			}
279			out = append(out, addr)
280		}
281		return out
282	}
283
284	for i, tt := range testCases {
285		dss, err := newDualStackServer()
286		if err != nil {
287			t.Fatal(err)
288		}
289		defer dss.teardown()
290		if err := dss.buildup(handler); err != nil {
291			t.Fatal(err)
292		}
293		if tt.teardownNetwork != "" {
294			// Destroy one of the listening sockets, creating an unreachable port.
295			dss.teardownNetwork(tt.teardownNetwork)
296		}
297
298		primaries := makeAddrs(tt.primaries, dss.port)
299		fallbacks := makeAddrs(tt.fallbacks, dss.port)
300		d := Dialer{
301			FallbackDelay: fallbackDelay,
302		}
303		startTime := time.Now()
304		sd := &sysDialer{
305			Dialer:  d,
306			network: "tcp",
307			address: "?",
308		}
309		c, err := sd.dialParallel(context.Background(), primaries, fallbacks)
310		elapsed := time.Since(startTime)
311
312		if c != nil {
313			c.Close()
314		}
315
316		if tt.expectOk && err != nil {
317			t.Errorf("#%d: got %v; want nil", i, err)
318		} else if !tt.expectOk && err == nil {
319			t.Errorf("#%d: got nil; want non-nil", i)
320		}
321
322		// We used to always use 95 milliseconds as the slop,
323		// but that was flaky on Windows.  See issue 35616.
324		slop := 95 * time.Millisecond
325		if fifth := tt.expectElapsed / 5; fifth > slop {
326			slop = fifth
327		}
328		expectElapsedMin := tt.expectElapsed - slop
329		expectElapsedMax := tt.expectElapsed + slop
330		if elapsed < expectElapsedMin {
331			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectElapsedMin)
332		} else if elapsed > expectElapsedMax {
333			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectElapsedMax)
334		}
335
336		// Repeat each case, ensuring that it can be canceled quickly.
337		ctx, cancel := context.WithCancel(context.Background())
338		var wg sync.WaitGroup
339		wg.Add(1)
340		go func() {
341			time.Sleep(5 * time.Millisecond)
342			cancel()
343			wg.Done()
344		}()
345		startTime = time.Now()
346		c, err = sd.dialParallel(ctx, primaries, fallbacks)
347		if c != nil {
348			c.Close()
349		}
350		elapsed = time.Now().Sub(startTime)
351		if elapsed > 100*time.Millisecond {
352			t.Errorf("#%d (cancel): got %v; want <= 100ms", i, elapsed)
353		}
354		wg.Wait()
355	}
356}
357
358func lookupSlowFast(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
359	switch host {
360	case "slow6loopback4":
361		// Returns a slow IPv6 address, and a local IPv4 address.
362		return []IPAddr{
363			{IP: ParseIP(slowDst6)},
364			{IP: ParseIP("127.0.0.1")},
365		}, nil
366	default:
367		return fn(ctx, network, host)
368	}
369}
370
371func TestDialerFallbackDelay(t *testing.T) {
372	testenv.MustHaveExternalNetwork(t)
373
374	if !supportsIPv4() || !supportsIPv6() {
375		t.Skip("both IPv4 and IPv6 are required")
376	}
377
378	origTestHookLookupIP := testHookLookupIP
379	defer func() { testHookLookupIP = origTestHookLookupIP }()
380	testHookLookupIP = lookupSlowFast
381
382	origTestHookDialTCP := testHookDialTCP
383	defer func() { testHookDialTCP = origTestHookDialTCP }()
384	testHookDialTCP = slowDialTCP
385
386	var testCases = []struct {
387		dualstack     bool
388		delay         time.Duration
389		expectElapsed time.Duration
390	}{
391		// Use a very brief delay, which should fallback immediately.
392		{true, 1 * time.Nanosecond, 0},
393		// Use a 200ms explicit timeout.
394		{true, 200 * time.Millisecond, 200 * time.Millisecond},
395		// The default is 300ms.
396		{true, 0, 300 * time.Millisecond},
397	}
398
399	handler := func(dss *dualStackServer, ln Listener) {
400		for {
401			c, err := ln.Accept()
402			if err != nil {
403				return
404			}
405			c.Close()
406		}
407	}
408	dss, err := newDualStackServer()
409	if err != nil {
410		t.Fatal(err)
411	}
412	defer dss.teardown()
413	if err := dss.buildup(handler); err != nil {
414		t.Fatal(err)
415	}
416
417	for i, tt := range testCases {
418		d := &Dialer{DualStack: tt.dualstack, FallbackDelay: tt.delay}
419
420		startTime := time.Now()
421		c, err := d.Dial("tcp", JoinHostPort("slow6loopback4", dss.port))
422		elapsed := time.Now().Sub(startTime)
423		if err == nil {
424			c.Close()
425		} else if tt.dualstack {
426			t.Error(err)
427		}
428		expectMin := tt.expectElapsed - 1*time.Millisecond
429		expectMax := tt.expectElapsed + 95*time.Millisecond
430		if elapsed < expectMin {
431			t.Errorf("#%d: got %v; want >= %v", i, elapsed, expectMin)
432		}
433		if elapsed > expectMax {
434			t.Errorf("#%d: got %v; want <= %v", i, elapsed, expectMax)
435		}
436	}
437}
438
439func TestDialParallelSpuriousConnection(t *testing.T) {
440	if !supportsIPv4() || !supportsIPv6() {
441		t.Skip("both IPv4 and IPv6 are required")
442	}
443
444	var wg sync.WaitGroup
445	wg.Add(2)
446	handler := func(dss *dualStackServer, ln Listener) {
447		// Accept one connection per address.
448		c, err := ln.Accept()
449		if err != nil {
450			t.Fatal(err)
451		}
452		// The client should close itself, without sending data.
453		c.SetReadDeadline(time.Now().Add(1 * time.Second))
454		var b [1]byte
455		if _, err := c.Read(b[:]); err != io.EOF {
456			t.Errorf("got %v; want %v", err, io.EOF)
457		}
458		c.Close()
459		wg.Done()
460	}
461	dss, err := newDualStackServer()
462	if err != nil {
463		t.Fatal(err)
464	}
465	defer dss.teardown()
466	if err := dss.buildup(handler); err != nil {
467		t.Fatal(err)
468	}
469
470	const fallbackDelay = 100 * time.Millisecond
471
472	origTestHookDialTCP := testHookDialTCP
473	defer func() { testHookDialTCP = origTestHookDialTCP }()
474	testHookDialTCP = func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
475		// Sleep long enough for Happy Eyeballs to kick in, and inhibit cancellation.
476		// This forces dialParallel to juggle two successful connections.
477		time.Sleep(fallbackDelay * 2)
478
479		// Now ignore the provided context (which will be canceled) and use a
480		// different one to make sure this completes with a valid connection,
481		// which we hope to be closed below:
482		sd := &sysDialer{network: net, address: raddr.String()}
483		return sd.doDialTCP(context.Background(), laddr, raddr)
484	}
485
486	d := Dialer{
487		FallbackDelay: fallbackDelay,
488	}
489	sd := &sysDialer{
490		Dialer:  d,
491		network: "tcp",
492		address: "?",
493	}
494
495	makeAddr := func(ip string) addrList {
496		addr, err := ResolveTCPAddr("tcp", JoinHostPort(ip, dss.port))
497		if err != nil {
498			t.Fatal(err)
499		}
500		return addrList{addr}
501	}
502
503	// dialParallel returns one connection (and closes the other.)
504	c, err := sd.dialParallel(context.Background(), makeAddr("127.0.0.1"), makeAddr("::1"))
505	if err != nil {
506		t.Fatal(err)
507	}
508	c.Close()
509
510	// The server should've seen both connections.
511	wg.Wait()
512}
513
514func TestDialerPartialDeadline(t *testing.T) {
515	now := time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
516	var testCases = []struct {
517		now            time.Time
518		deadline       time.Time
519		addrs          int
520		expectDeadline time.Time
521		expectErr      error
522	}{
523		// Regular division.
524		{now, now.Add(12 * time.Second), 1, now.Add(12 * time.Second), nil},
525		{now, now.Add(12 * time.Second), 2, now.Add(6 * time.Second), nil},
526		{now, now.Add(12 * time.Second), 3, now.Add(4 * time.Second), nil},
527		// Bump against the 2-second sane minimum.
528		{now, now.Add(12 * time.Second), 999, now.Add(2 * time.Second), nil},
529		// Total available is now below the sane minimum.
530		{now, now.Add(1900 * time.Millisecond), 999, now.Add(1900 * time.Millisecond), nil},
531		// Null deadline.
532		{now, noDeadline, 1, noDeadline, nil},
533		// Step the clock forward and cross the deadline.
534		{now.Add(-1 * time.Millisecond), now, 1, now, nil},
535		{now.Add(0 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
536		{now.Add(1 * time.Millisecond), now, 1, noDeadline, poll.ErrTimeout},
537	}
538	for i, tt := range testCases {
539		deadline, err := partialDeadline(tt.now, tt.deadline, tt.addrs)
540		if err != tt.expectErr {
541			t.Errorf("#%d: got %v; want %v", i, err, tt.expectErr)
542		}
543		if !deadline.Equal(tt.expectDeadline) {
544			t.Errorf("#%d: got %v; want %v", i, deadline, tt.expectDeadline)
545		}
546	}
547}
548
549func TestDialerLocalAddr(t *testing.T) {
550	if !supportsIPv4() || !supportsIPv6() {
551		t.Skip("both IPv4 and IPv6 are required")
552	}
553
554	type test struct {
555		network, raddr string
556		laddr          Addr
557		error
558	}
559	var tests = []test{
560		{"tcp4", "127.0.0.1", nil, nil},
561		{"tcp4", "127.0.0.1", &TCPAddr{}, nil},
562		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
563		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
564		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"}},
565		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
566		{"tcp4", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
567		{"tcp4", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
568		{"tcp4", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
569		{"tcp4", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
570
571		{"tcp6", "::1", nil, nil},
572		{"tcp6", "::1", &TCPAddr{}, nil},
573		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
574		{"tcp6", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
575		{"tcp6", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
576		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
577		{"tcp6", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
578		{"tcp6", "::1", &TCPAddr{IP: IPv6loopback}, nil},
579		{"tcp6", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
580		{"tcp6", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
581
582		{"tcp", "127.0.0.1", nil, nil},
583		{"tcp", "127.0.0.1", &TCPAddr{}, nil},
584		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
585		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
586		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, nil},
587		{"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, nil},
588		{"tcp", "127.0.0.1", &TCPAddr{IP: IPv6loopback}, errNoSuitableAddress},
589		{"tcp", "127.0.0.1", &UDPAddr{}, &AddrError{Err: "some error"}},
590		{"tcp", "127.0.0.1", &UnixAddr{}, &AddrError{Err: "some error"}},
591
592		{"tcp", "::1", nil, nil},
593		{"tcp", "::1", &TCPAddr{}, nil},
594		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0")}, nil},
595		{"tcp", "::1", &TCPAddr{IP: ParseIP("0.0.0.0").To4()}, nil},
596		{"tcp", "::1", &TCPAddr{IP: ParseIP("::")}, nil},
597		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To4()}, errNoSuitableAddress},
598		{"tcp", "::1", &TCPAddr{IP: ParseIP("127.0.0.1").To16()}, errNoSuitableAddress},
599		{"tcp", "::1", &TCPAddr{IP: IPv6loopback}, nil},
600		{"tcp", "::1", &UDPAddr{}, &AddrError{Err: "some error"}},
601		{"tcp", "::1", &UnixAddr{}, &AddrError{Err: "some error"}},
602	}
603
604	if supportsIPv4map() {
605		tests = append(tests, test{
606			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, nil,
607		})
608	} else {
609		tests = append(tests, test{
610			"tcp", "127.0.0.1", &TCPAddr{IP: ParseIP("::")}, &AddrError{Err: "some error"},
611		})
612	}
613
614	origTestHookLookupIP := testHookLookupIP
615	defer func() { testHookLookupIP = origTestHookLookupIP }()
616	testHookLookupIP = lookupLocalhost
617	handler := func(ls *localServer, ln Listener) {
618		for {
619			c, err := ln.Accept()
620			if err != nil {
621				return
622			}
623			c.Close()
624		}
625	}
626	var err error
627	var lss [2]*localServer
628	for i, network := range []string{"tcp4", "tcp6"} {
629		lss[i], err = newLocalServer(network)
630		if err != nil {
631			t.Fatal(err)
632		}
633		defer lss[i].teardown()
634		if err := lss[i].buildup(handler); err != nil {
635			t.Fatal(err)
636		}
637	}
638
639	for _, tt := range tests {
640		d := &Dialer{LocalAddr: tt.laddr}
641		var addr string
642		ip := ParseIP(tt.raddr)
643		if ip.To4() != nil {
644			addr = lss[0].Listener.Addr().String()
645		}
646		if ip.To16() != nil && ip.To4() == nil {
647			addr = lss[1].Listener.Addr().String()
648		}
649		c, err := d.Dial(tt.network, addr)
650		if err == nil && tt.error != nil || err != nil && tt.error == nil {
651			// A suspected kernel bug in macOS 10.12 occasionally results in
652			// timeout errors when dialing address ::1. The errors have not
653			// been observed on newer versions of the OS, so we don't plan to work
654			// around them. See https://golang.org/issue/22019.
655			if tt.raddr == "::1" && os.Getenv("GO_BUILDER_NAME") == "darwin-amd64-10_12" && os.IsTimeout(err) {
656				t.Logf("ignoring timeout error on Darwin; see https://golang.org/issue/22019")
657			} else {
658				t.Errorf("%s %v->%s: got %v; want %v", tt.network, tt.laddr, tt.raddr, err, tt.error)
659			}
660		}
661		if err != nil {
662			if perr := parseDialError(err); perr != nil {
663				t.Error(perr)
664			}
665			continue
666		}
667		c.Close()
668	}
669}
670
671func TestDialerDualStack(t *testing.T) {
672	testenv.SkipFlaky(t, 13324)
673
674	if !supportsIPv4() || !supportsIPv6() {
675		t.Skip("both IPv4 and IPv6 are required")
676	}
677
678	closedPortDelay, expectClosedPortDelay := dialClosedPort(t)
679	if closedPortDelay > expectClosedPortDelay {
680		t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
681	}
682
683	origTestHookLookupIP := testHookLookupIP
684	defer func() { testHookLookupIP = origTestHookLookupIP }()
685	testHookLookupIP = lookupLocalhost
686	handler := func(dss *dualStackServer, ln Listener) {
687		for {
688			c, err := ln.Accept()
689			if err != nil {
690				return
691			}
692			c.Close()
693		}
694	}
695
696	var timeout = 150*time.Millisecond + closedPortDelay
697	for _, dualstack := range []bool{false, true} {
698		dss, err := newDualStackServer()
699		if err != nil {
700			t.Fatal(err)
701		}
702		defer dss.teardown()
703		if err := dss.buildup(handler); err != nil {
704			t.Fatal(err)
705		}
706
707		d := &Dialer{DualStack: dualstack, Timeout: timeout}
708		for range dss.lns {
709			c, err := d.Dial("tcp", JoinHostPort("localhost", dss.port))
710			if err != nil {
711				t.Error(err)
712				continue
713			}
714			switch addr := c.LocalAddr().(*TCPAddr); {
715			case addr.IP.To4() != nil:
716				dss.teardownNetwork("tcp4")
717			case addr.IP.To16() != nil && addr.IP.To4() == nil:
718				dss.teardownNetwork("tcp6")
719			}
720			c.Close()
721		}
722	}
723}
724
725func TestDialerKeepAlive(t *testing.T) {
726	handler := func(ls *localServer, ln Listener) {
727		for {
728			c, err := ln.Accept()
729			if err != nil {
730				return
731			}
732			c.Close()
733		}
734	}
735	ls, err := newLocalServer("tcp")
736	if err != nil {
737		t.Fatal(err)
738	}
739	defer ls.teardown()
740	if err := ls.buildup(handler); err != nil {
741		t.Fatal(err)
742	}
743	defer func() { testHookSetKeepAlive = func(time.Duration) {} }()
744
745	tests := []struct {
746		ka       time.Duration
747		expected time.Duration
748	}{
749		{-1, -1},
750		{0, 15 * time.Second},
751		{5 * time.Second, 5 * time.Second},
752		{30 * time.Second, 30 * time.Second},
753	}
754
755	for _, test := range tests {
756		var got time.Duration = -1
757		testHookSetKeepAlive = func(d time.Duration) { got = d }
758		d := Dialer{KeepAlive: test.ka}
759		c, err := d.Dial("tcp", ls.Listener.Addr().String())
760		if err != nil {
761			t.Fatal(err)
762		}
763		c.Close()
764		if got != test.expected {
765			t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive set to %v, want %v", d.KeepAlive, got, test.expected)
766		}
767	}
768}
769
770func TestDialCancel(t *testing.T) {
771	mustHaveExternalNetwork(t)
772
773	blackholeIPPort := JoinHostPort(slowDst4, "1234")
774	if !supportsIPv4() {
775		blackholeIPPort = JoinHostPort(slowDst6, "1234")
776	}
777
778	ticker := time.NewTicker(10 * time.Millisecond)
779	defer ticker.Stop()
780
781	const cancelTick = 5 // the timer tick we cancel the dial at
782	const timeoutTick = 100
783
784	var d Dialer
785	cancel := make(chan struct{})
786	d.Cancel = cancel
787	errc := make(chan error, 1)
788	connc := make(chan Conn, 1)
789	go func() {
790		if c, err := d.Dial("tcp", blackholeIPPort); err != nil {
791			errc <- err
792		} else {
793			connc <- c
794		}
795	}()
796	ticks := 0
797	for {
798		select {
799		case <-ticker.C:
800			ticks++
801			if ticks == cancelTick {
802				close(cancel)
803			}
804			if ticks == timeoutTick {
805				t.Fatal("timeout waiting for dial to fail")
806			}
807		case c := <-connc:
808			c.Close()
809			t.Fatal("unexpected successful connection")
810		case err := <-errc:
811			if perr := parseDialError(err); perr != nil {
812				t.Error(perr)
813			}
814			if ticks < cancelTick {
815				// Using strings.Contains is ugly but
816				// may work on plan9 and windows.
817				if strings.Contains(err.Error(), "connection refused") {
818					t.Skipf("connection to %v failed fast with %v", blackholeIPPort, err)
819				}
820				t.Fatalf("dial error after %d ticks (%d before cancel sent): %v",
821					ticks, cancelTick-ticks, err)
822			}
823			if oe, ok := err.(*OpError); !ok || oe.Err != errCanceled {
824				t.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err, err)
825			}
826			return // success.
827		}
828	}
829}
830
831func TestCancelAfterDial(t *testing.T) {
832	if testing.Short() {
833		t.Skip("avoiding time.Sleep")
834	}
835
836	ln, err := newLocalListener("tcp")
837	if err != nil {
838		t.Fatal(err)
839	}
840
841	var wg sync.WaitGroup
842	wg.Add(1)
843	defer func() {
844		ln.Close()
845		wg.Wait()
846	}()
847
848	// Echo back the first line of each incoming connection.
849	go func() {
850		for {
851			c, err := ln.Accept()
852			if err != nil {
853				break
854			}
855			rb := bufio.NewReader(c)
856			line, err := rb.ReadString('\n')
857			if err != nil {
858				t.Error(err)
859				c.Close()
860				continue
861			}
862			if _, err := c.Write([]byte(line)); err != nil {
863				t.Error(err)
864			}
865			c.Close()
866		}
867		wg.Done()
868	}()
869
870	try := func() {
871		cancel := make(chan struct{})
872		d := &Dialer{Cancel: cancel}
873		c, err := d.Dial("tcp", ln.Addr().String())
874
875		// Immediately after dialing, request cancellation and sleep.
876		// Before Issue 15078 was fixed, this would cause subsequent operations
877		// to fail with an i/o timeout roughly 50% of the time.
878		close(cancel)
879		time.Sleep(10 * time.Millisecond)
880
881		if err != nil {
882			t.Fatal(err)
883		}
884		defer c.Close()
885
886		// Send some data to confirm that the connection is still alive.
887		const message = "echo!\n"
888		if _, err := c.Write([]byte(message)); err != nil {
889			t.Fatal(err)
890		}
891
892		// The server should echo the line, and close the connection.
893		rb := bufio.NewReader(c)
894		line, err := rb.ReadString('\n')
895		if err != nil {
896			t.Fatal(err)
897		}
898		if line != message {
899			t.Errorf("got %q; want %q", line, message)
900		}
901		if _, err := rb.ReadByte(); err != io.EOF {
902			t.Errorf("got %v; want %v", err, io.EOF)
903		}
904	}
905
906	// This bug manifested about 50% of the time, so try it a few times.
907	for i := 0; i < 10; i++ {
908		try()
909	}
910}
911
912// Issue 18806: it should always be possible to net.Dial a
913// net.Listener().Addr().String when the listen address was ":n", even
914// if the machine has halfway configured IPv6 such that it can bind on
915// "::" not connect back to that same address.
916func TestDialListenerAddr(t *testing.T) {
917	mustHaveExternalNetwork(t)
918	ln, err := Listen("tcp", ":0")
919	if err != nil {
920		t.Fatal(err)
921	}
922	defer ln.Close()
923	addr := ln.Addr().String()
924	c, err := Dial("tcp", addr)
925	if err != nil {
926		t.Fatalf("for addr %q, dial error: %v", addr, err)
927	}
928	c.Close()
929}
930
931func TestDialerControl(t *testing.T) {
932	switch runtime.GOOS {
933	case "plan9":
934		t.Skipf("not supported on %s", runtime.GOOS)
935	}
936
937	t.Run("StreamDial", func(t *testing.T) {
938		for _, network := range []string{"tcp", "tcp4", "tcp6", "unix", "unixpacket"} {
939			if !testableNetwork(network) {
940				continue
941			}
942			ln, err := newLocalListener(network)
943			if err != nil {
944				t.Error(err)
945				continue
946			}
947			defer ln.Close()
948			d := Dialer{Control: controlOnConnSetup}
949			c, err := d.Dial(network, ln.Addr().String())
950			if err != nil {
951				t.Error(err)
952				continue
953			}
954			c.Close()
955		}
956	})
957	t.Run("PacketDial", func(t *testing.T) {
958		for _, network := range []string{"udp", "udp4", "udp6", "unixgram"} {
959			if !testableNetwork(network) {
960				continue
961			}
962			c1, err := newLocalPacketListener(network)
963			if err != nil {
964				t.Error(err)
965				continue
966			}
967			if network == "unixgram" {
968				defer os.Remove(c1.LocalAddr().String())
969			}
970			defer c1.Close()
971			d := Dialer{Control: controlOnConnSetup}
972			c2, err := d.Dial(network, c1.LocalAddr().String())
973			if err != nil {
974				t.Error(err)
975				continue
976			}
977			c2.Close()
978		}
979	})
980}
981
982// mustHaveExternalNetwork is like testenv.MustHaveExternalNetwork
983// except that it won't skip testing on non-mobile builders.
984func mustHaveExternalNetwork(t *testing.T) {
985	t.Helper()
986	mobile := runtime.GOOS == "android" || runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")
987	if testenv.Builder() == "" || mobile {
988		testenv.MustHaveExternalNetwork(t)
989	}
990}
991
992type contextWithNonZeroDeadline struct {
993	context.Context
994}
995
996func (contextWithNonZeroDeadline) Deadline() (time.Time, bool) {
997	// Return non-zero time.Time value with false indicating that no deadline is set.
998	return time.Unix(0, 0), false
999}
1000
1001func TestDialWithNonZeroDeadline(t *testing.T) {
1002	ln, err := newLocalListener("tcp")
1003	if err != nil {
1004		t.Fatal(err)
1005	}
1006	defer ln.Close()
1007	_, port, err := SplitHostPort(ln.Addr().String())
1008	if err != nil {
1009		t.Fatal(err)
1010	}
1011
1012	ctx := contextWithNonZeroDeadline{Context: context.Background()}
1013	var dialer Dialer
1014	c, err := dialer.DialContext(ctx, "tcp", JoinHostPort("", port))
1015	if err != nil {
1016		t.Fatal(err)
1017	}
1018	c.Close()
1019}
1020