Source file
src/net/listen_test.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "fmt"
12 "internal/testenv"
13 "os"
14 "runtime"
15 "syscall"
16 "testing"
17 "time"
18 )
19
20 func (ln *TCPListener) port() string {
21 _, port, err := SplitHostPort(ln.Addr().String())
22 if err != nil {
23 return ""
24 }
25 return port
26 }
27
28 func (c *UDPConn) port() string {
29 _, port, err := SplitHostPort(c.LocalAddr().String())
30 if err != nil {
31 return ""
32 }
33 return port
34 }
35
36 var tcpListenerTests = []struct {
37 network string
38 address string
39 }{
40 {"tcp", ""},
41 {"tcp", "0.0.0.0"},
42 {"tcp", "::ffff:0.0.0.0"},
43 {"tcp", "::"},
44
45 {"tcp", "127.0.0.1"},
46 {"tcp", "::ffff:127.0.0.1"},
47 {"tcp", "::1"},
48
49 {"tcp4", ""},
50 {"tcp4", "0.0.0.0"},
51 {"tcp4", "::ffff:0.0.0.0"},
52
53 {"tcp4", "127.0.0.1"},
54 {"tcp4", "::ffff:127.0.0.1"},
55
56 {"tcp6", ""},
57 {"tcp6", "::"},
58
59 {"tcp6", "::1"},
60 }
61
62
63
64
65 func TestTCPListener(t *testing.T) {
66 switch runtime.GOOS {
67 case "plan9":
68 t.Skipf("not supported on %s", runtime.GOOS)
69 }
70
71 for _, tt := range tcpListenerTests {
72 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
73 t.Logf("skipping %s test", tt.network+" "+tt.address)
74 continue
75 }
76
77 ln1, err := Listen(tt.network, JoinHostPort(tt.address, "0"))
78 if err != nil {
79 t.Fatal(err)
80 }
81 if err := checkFirstListener(tt.network, ln1); err != nil {
82 ln1.Close()
83 t.Fatal(err)
84 }
85 ln2, err := Listen(tt.network, JoinHostPort(tt.address, ln1.(*TCPListener).port()))
86 if err == nil {
87 ln2.Close()
88 }
89 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
90 ln1.Close()
91 t.Fatal(err)
92 }
93 ln1.Close()
94 }
95 }
96
97 var udpListenerTests = []struct {
98 network string
99 address string
100 }{
101 {"udp", ""},
102 {"udp", "0.0.0.0"},
103 {"udp", "::ffff:0.0.0.0"},
104 {"udp", "::"},
105
106 {"udp", "127.0.0.1"},
107 {"udp", "::ffff:127.0.0.1"},
108 {"udp", "::1"},
109
110 {"udp4", ""},
111 {"udp4", "0.0.0.0"},
112 {"udp4", "::ffff:0.0.0.0"},
113
114 {"udp4", "127.0.0.1"},
115 {"udp4", "::ffff:127.0.0.1"},
116
117 {"udp6", ""},
118 {"udp6", "::"},
119
120 {"udp6", "::1"},
121 }
122
123
124
125
126 func TestUDPListener(t *testing.T) {
127 switch runtime.GOOS {
128 case "plan9":
129 t.Skipf("not supported on %s", runtime.GOOS)
130 }
131
132 for _, tt := range udpListenerTests {
133 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
134 t.Logf("skipping %s test", tt.network+" "+tt.address)
135 continue
136 }
137
138 c1, err := ListenPacket(tt.network, JoinHostPort(tt.address, "0"))
139 if err != nil {
140 t.Fatal(err)
141 }
142 if err := checkFirstListener(tt.network, c1); err != nil {
143 c1.Close()
144 t.Fatal(err)
145 }
146 c2, err := ListenPacket(tt.network, JoinHostPort(tt.address, c1.(*UDPConn).port()))
147 if err == nil {
148 c2.Close()
149 }
150 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
151 c1.Close()
152 t.Fatal(err)
153 }
154 c1.Close()
155 }
156 }
157
158 var dualStackTCPListenerTests = []struct {
159 network1, address1 string
160 network2, address2 string
161 xerr error
162 }{
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 {"tcp", "", "tcp", "", syscall.EADDRINUSE},
198 {"tcp", "", "tcp", "0.0.0.0", syscall.EADDRINUSE},
199 {"tcp", "0.0.0.0", "tcp", "", syscall.EADDRINUSE},
200
201 {"tcp", "", "tcp", "::", syscall.EADDRINUSE},
202 {"tcp", "::", "tcp", "", syscall.EADDRINUSE},
203 {"tcp", "0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
204 {"tcp", "::", "tcp", "0.0.0.0", syscall.EADDRINUSE},
205 {"tcp", "::ffff:0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
206 {"tcp", "::", "tcp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
207
208 {"tcp4", "", "tcp6", "", nil},
209 {"tcp6", "", "tcp4", "", nil},
210 {"tcp4", "0.0.0.0", "tcp6", "::", nil},
211 {"tcp6", "::", "tcp4", "0.0.0.0", nil},
212
213 {"tcp", "127.0.0.1", "tcp", "::1", nil},
214 {"tcp", "::1", "tcp", "127.0.0.1", nil},
215 {"tcp4", "127.0.0.1", "tcp6", "::1", nil},
216 {"tcp6", "::1", "tcp4", "127.0.0.1", nil},
217 }
218
219
220
221
222
223
224
225 func TestDualStackTCPListener(t *testing.T) {
226 switch runtime.GOOS {
227 case "plan9":
228 t.Skipf("not supported on %s", runtime.GOOS)
229 }
230 if !supportsIPv4() || !supportsIPv6() {
231 t.Skip("both IPv4 and IPv6 are required")
232 }
233
234 for _, tt := range dualStackTCPListenerTests {
235 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
236 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
237 continue
238 }
239
240 if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
241 tt.xerr = nil
242 }
243 var firstErr, secondErr error
244 for i := 0; i < 5; i++ {
245 lns, err := newDualStackListener()
246 if err != nil {
247 t.Fatal(err)
248 }
249 port := lns[0].port()
250 for _, ln := range lns {
251 ln.Close()
252 }
253 var ln1 Listener
254 ln1, firstErr = Listen(tt.network1, JoinHostPort(tt.address1, port))
255 if firstErr != nil {
256 continue
257 }
258 if err := checkFirstListener(tt.network1, ln1); err != nil {
259 ln1.Close()
260 t.Fatal(err)
261 }
262 ln2, err := Listen(tt.network2, JoinHostPort(tt.address2, ln1.(*TCPListener).port()))
263 if err == nil {
264 ln2.Close()
265 }
266 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
267 ln1.Close()
268 continue
269 }
270 ln1.Close()
271 break
272 }
273 if firstErr != nil {
274 t.Error(firstErr)
275 }
276 if secondErr != nil {
277 t.Error(secondErr)
278 }
279 }
280 }
281
282 var dualStackUDPListenerTests = []struct {
283 network1, address1 string
284 network2, address2 string
285 xerr error
286 }{
287 {"udp", "", "udp", "", syscall.EADDRINUSE},
288 {"udp", "", "udp", "0.0.0.0", syscall.EADDRINUSE},
289 {"udp", "0.0.0.0", "udp", "", syscall.EADDRINUSE},
290
291 {"udp", "", "udp", "::", syscall.EADDRINUSE},
292 {"udp", "::", "udp", "", syscall.EADDRINUSE},
293 {"udp", "0.0.0.0", "udp", "::", syscall.EADDRINUSE},
294 {"udp", "::", "udp", "0.0.0.0", syscall.EADDRINUSE},
295 {"udp", "::ffff:0.0.0.0", "udp", "::", syscall.EADDRINUSE},
296 {"udp", "::", "udp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
297
298 {"udp4", "", "udp6", "", nil},
299 {"udp6", "", "udp4", "", nil},
300 {"udp4", "0.0.0.0", "udp6", "::", nil},
301 {"udp6", "::", "udp4", "0.0.0.0", nil},
302
303 {"udp", "127.0.0.1", "udp", "::1", nil},
304 {"udp", "::1", "udp", "127.0.0.1", nil},
305 {"udp4", "127.0.0.1", "udp6", "::1", nil},
306 {"udp6", "::1", "udp4", "127.0.0.1", nil},
307 }
308
309
310
311
312
313
314
315 func TestDualStackUDPListener(t *testing.T) {
316 switch runtime.GOOS {
317 case "plan9":
318 t.Skipf("not supported on %s", runtime.GOOS)
319 }
320 if !supportsIPv4() || !supportsIPv6() {
321 t.Skip("both IPv4 and IPv6 are required")
322 }
323
324 for _, tt := range dualStackUDPListenerTests {
325 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
326 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
327 continue
328 }
329
330 if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
331 tt.xerr = nil
332 }
333 var firstErr, secondErr error
334 for i := 0; i < 5; i++ {
335 cs, err := newDualStackPacketListener()
336 if err != nil {
337 t.Fatal(err)
338 }
339 port := cs[0].port()
340 for _, c := range cs {
341 c.Close()
342 }
343 var c1 PacketConn
344 c1, firstErr = ListenPacket(tt.network1, JoinHostPort(tt.address1, port))
345 if firstErr != nil {
346 continue
347 }
348 if err := checkFirstListener(tt.network1, c1); err != nil {
349 c1.Close()
350 t.Fatal(err)
351 }
352 c2, err := ListenPacket(tt.network2, JoinHostPort(tt.address2, c1.(*UDPConn).port()))
353 if err == nil {
354 c2.Close()
355 }
356 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
357 c1.Close()
358 continue
359 }
360 c1.Close()
361 break
362 }
363 if firstErr != nil {
364 t.Error(firstErr)
365 }
366 if secondErr != nil {
367 t.Error(secondErr)
368 }
369 }
370 }
371
372 func differentWildcardAddr(i, j string) bool {
373 if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
374 return false
375 }
376 if i == "[::]" && j == "[::]" {
377 return false
378 }
379 return true
380 }
381
382 func checkFirstListener(network string, ln any) error {
383 switch network {
384 case "tcp":
385 fd := ln.(*TCPListener).fd
386 if err := checkDualStackAddrFamily(fd); err != nil {
387 return err
388 }
389 case "tcp4":
390 fd := ln.(*TCPListener).fd
391 if fd.family != syscall.AF_INET {
392 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
393 }
394 case "tcp6":
395 fd := ln.(*TCPListener).fd
396 if fd.family != syscall.AF_INET6 {
397 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
398 }
399 case "udp":
400 fd := ln.(*UDPConn).fd
401 if err := checkDualStackAddrFamily(fd); err != nil {
402 return err
403 }
404 case "udp4":
405 fd := ln.(*UDPConn).fd
406 if fd.family != syscall.AF_INET {
407 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
408 }
409 case "udp6":
410 fd := ln.(*UDPConn).fd
411 if fd.family != syscall.AF_INET6 {
412 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
413 }
414 default:
415 return UnknownNetworkError(network)
416 }
417 return nil
418 }
419
420 func checkSecondListener(network, address string, err error) error {
421 switch network {
422 case "tcp", "tcp4", "tcp6":
423 if err == nil {
424 return fmt.Errorf("%s should fail", network+" "+address)
425 }
426 case "udp", "udp4", "udp6":
427 if err == nil {
428 return fmt.Errorf("%s should fail", network+" "+address)
429 }
430 default:
431 return UnknownNetworkError(network)
432 }
433 return nil
434 }
435
436 func checkDualStackSecondListener(network, address string, err, xerr error) error {
437 switch network {
438 case "tcp", "tcp4", "tcp6":
439 if xerr == nil && err != nil || xerr != nil && err == nil {
440 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
441 }
442 case "udp", "udp4", "udp6":
443 if xerr == nil && err != nil || xerr != nil && err == nil {
444 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
445 }
446 default:
447 return UnknownNetworkError(network)
448 }
449 return nil
450 }
451
452 func checkDualStackAddrFamily(fd *netFD) error {
453 switch a := fd.laddr.(type) {
454 case *TCPAddr:
455
456
457
458
459 if supportsIPv4map() && fd.laddr.(*TCPAddr).isWildcard() {
460 if fd.family != syscall.AF_INET6 {
461 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
462 }
463 } else {
464 if fd.family != a.family() {
465 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
466 }
467 }
468 case *UDPAddr:
469
470
471
472
473 if supportsIPv4map() && fd.laddr.(*UDPAddr).isWildcard() {
474 if fd.family != syscall.AF_INET6 {
475 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
476 }
477 } else {
478 if fd.family != a.family() {
479 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
480 }
481 }
482 default:
483 return fmt.Errorf("unexpected protocol address type: %T", a)
484 }
485 return nil
486 }
487
488 func TestWildWildcardListener(t *testing.T) {
489 testenv.MustHaveExternalNetwork(t)
490
491 switch runtime.GOOS {
492 case "plan9":
493 t.Skipf("not supported on %s", runtime.GOOS)
494 }
495
496 defer func() {
497 if p := recover(); p != nil {
498 t.Fatalf("panicked: %v", p)
499 }
500 }()
501
502 if ln, err := Listen("tcp", ""); err == nil {
503 ln.Close()
504 }
505 if ln, err := ListenPacket("udp", ""); err == nil {
506 ln.Close()
507 }
508 if ln, err := ListenTCP("tcp", nil); err == nil {
509 ln.Close()
510 }
511 if ln, err := ListenUDP("udp", nil); err == nil {
512 ln.Close()
513 }
514 if ln, err := ListenIP("ip:icmp", nil); err == nil {
515 ln.Close()
516 }
517 }
518
519 var ipv4MulticastListenerTests = []struct {
520 net string
521 gaddr *UDPAddr
522 }{
523 {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
524
525 {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
526 }
527
528
529
530
531 func TestIPv4MulticastListener(t *testing.T) {
532 testenv.MustHaveExternalNetwork(t)
533
534 switch runtime.GOOS {
535 case "android", "plan9":
536 t.Skipf("not supported on %s", runtime.GOOS)
537 }
538 if !supportsIPv4() {
539 t.Skip("IPv4 is not supported")
540 }
541
542 closer := func(cs []*UDPConn) {
543 for _, c := range cs {
544 if c != nil {
545 c.Close()
546 }
547 }
548 }
549
550 for _, ifi := range []*Interface{loopbackInterface(), nil} {
551
552
553
554
555
556 if ifi == nil || !*testIPv4 {
557 continue
558 }
559 for _, tt := range ipv4MulticastListenerTests {
560 var err error
561 cs := make([]*UDPConn, 2)
562 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
563 t.Fatal(err)
564 }
565 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
566 closer(cs)
567 t.Fatal(err)
568 }
569 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
570 closer(cs)
571 t.Fatal(err)
572 }
573 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
574 closer(cs)
575 t.Fatal(err)
576 }
577 closer(cs)
578 }
579 }
580 }
581
582 var ipv6MulticastListenerTests = []struct {
583 net string
584 gaddr *UDPAddr
585 }{
586 {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
587 {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
588 {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
589 {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
590 {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
591 {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
592
593 {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
594 {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
595 {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
596 {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
597 {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
598 {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
599 }
600
601
602
603
604 func TestIPv6MulticastListener(t *testing.T) {
605 testenv.MustHaveExternalNetwork(t)
606
607 switch runtime.GOOS {
608 case "plan9":
609 t.Skipf("not supported on %s", runtime.GOOS)
610 }
611 if !supportsIPv6() {
612 t.Skip("IPv6 is not supported")
613 }
614 if os.Getuid() != 0 {
615 t.Skip("must be root")
616 }
617
618 closer := func(cs []*UDPConn) {
619 for _, c := range cs {
620 if c != nil {
621 c.Close()
622 }
623 }
624 }
625
626 for _, ifi := range []*Interface{loopbackInterface(), nil} {
627
628
629
630
631
632 if ifi == nil && !*testIPv6 {
633 continue
634 }
635 for _, tt := range ipv6MulticastListenerTests {
636 var err error
637 cs := make([]*UDPConn, 2)
638 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
639 t.Fatal(err)
640 }
641 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
642 closer(cs)
643 t.Fatal(err)
644 }
645 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
646 closer(cs)
647 t.Fatal(err)
648 }
649 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
650 closer(cs)
651 t.Fatal(err)
652 }
653 closer(cs)
654 }
655 }
656 }
657
658 func checkMulticastListener(c *UDPConn, ip IP) error {
659 if ok, err := multicastRIBContains(ip); err != nil {
660 return err
661 } else if !ok {
662 return fmt.Errorf("%s not found in multicast rib", ip.String())
663 }
664 la := c.LocalAddr()
665 if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
666 return fmt.Errorf("got %v; want a proper address with non-zero port number", la)
667 }
668 return nil
669 }
670
671 func multicastRIBContains(ip IP) (bool, error) {
672 switch runtime.GOOS {
673 case "aix", "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "illumos", "windows":
674 return true, nil
675 case "linux":
676 if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
677 return true, nil
678 }
679 }
680 ift, err := Interfaces()
681 if err != nil {
682 return false, err
683 }
684 for _, ifi := range ift {
685 ifmat, err := ifi.MulticastAddrs()
686 if err != nil {
687 return false, err
688 }
689 for _, ifma := range ifmat {
690 if ifma.(*IPAddr).IP.Equal(ip) {
691 return true, nil
692 }
693 }
694 }
695 return false, nil
696 }
697
698
699 func TestClosingListener(t *testing.T) {
700 ln := newLocalListener(t, "tcp")
701 addr := ln.Addr()
702
703 go func() {
704 for {
705 c, err := ln.Accept()
706 if err != nil {
707 return
708 }
709 c.Close()
710 }
711 }()
712
713
714
715
716 time.Sleep(time.Millisecond)
717
718 ln.Close()
719
720 ln2, err := Listen("tcp", addr.String())
721 if err != nil {
722 t.Fatal(err)
723 }
724 ln2.Close()
725 }
726
727 func TestListenConfigControl(t *testing.T) {
728 switch runtime.GOOS {
729 case "plan9":
730 t.Skipf("not supported on %s", runtime.GOOS)
731 }
732
733 t.Run("StreamListen", func(t *testing.T) {
734 for _, network := range []string{"tcp", "tcp4", "tcp6", "unix", "unixpacket"} {
735 if !testableNetwork(network) {
736 continue
737 }
738 ln := newLocalListener(t, network)
739 address := ln.Addr().String()
740
741
742 ln.Close()
743 lc := ListenConfig{Control: controlOnConnSetup}
744 ln, err := lc.Listen(context.Background(), network, address)
745 if err != nil {
746 t.Error(err)
747 continue
748 }
749 ln.Close()
750 }
751 })
752 t.Run("PacketListen", func(t *testing.T) {
753 for _, network := range []string{"udp", "udp4", "udp6", "unixgram"} {
754 if !testableNetwork(network) {
755 continue
756 }
757 c := newLocalPacketListener(t, network)
758 address := c.LocalAddr().String()
759
760
761 c.Close()
762 if network == "unixgram" {
763 os.Remove(address)
764 }
765 lc := ListenConfig{Control: controlOnConnSetup}
766 c, err := lc.ListenPacket(context.Background(), network, address)
767 if err != nil {
768 t.Error(err)
769 continue
770 }
771 c.Close()
772 if network == "unixgram" {
773 os.Remove(address)
774 }
775 }
776 })
777 }
778
View as plain text