Source file
src/net/listen_test.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "fmt"
11 "internal/testenv"
12 "os"
13 "runtime"
14 "syscall"
15 "testing"
16 "time"
17 )
18
19 func (ln *TCPListener) port() string {
20 _, port, err := SplitHostPort(ln.Addr().String())
21 if err != nil {
22 return ""
23 }
24 return port
25 }
26
27 func (c *UDPConn) port() string {
28 _, port, err := SplitHostPort(c.LocalAddr().String())
29 if err != nil {
30 return ""
31 }
32 return port
33 }
34
35 var tcpListenerTests = []struct {
36 network string
37 address string
38 }{
39 {"tcp", ""},
40 {"tcp", "0.0.0.0"},
41 {"tcp", "::ffff:0.0.0.0"},
42 {"tcp", "::"},
43
44 {"tcp", "127.0.0.1"},
45 {"tcp", "::ffff:127.0.0.1"},
46 {"tcp", "::1"},
47
48 {"tcp4", ""},
49 {"tcp4", "0.0.0.0"},
50 {"tcp4", "::ffff:0.0.0.0"},
51
52 {"tcp4", "127.0.0.1"},
53 {"tcp4", "::ffff:127.0.0.1"},
54
55 {"tcp6", ""},
56 {"tcp6", "::"},
57
58 {"tcp6", "::1"},
59 }
60
61
62
63
64 func TestTCPListener(t *testing.T) {
65 switch runtime.GOOS {
66 case "plan9":
67 t.Skipf("not supported on %s", runtime.GOOS)
68 }
69
70 for _, tt := range tcpListenerTests {
71 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
72 t.Logf("skipping %s test", tt.network+" "+tt.address)
73 continue
74 }
75
76 ln1, err := Listen(tt.network, JoinHostPort(tt.address, "0"))
77 if err != nil {
78 t.Fatal(err)
79 }
80 if err := checkFirstListener(tt.network, ln1); err != nil {
81 ln1.Close()
82 t.Fatal(err)
83 }
84 ln2, err := Listen(tt.network, JoinHostPort(tt.address, ln1.(*TCPListener).port()))
85 if err == nil {
86 ln2.Close()
87 }
88 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
89 ln1.Close()
90 t.Fatal(err)
91 }
92 ln1.Close()
93 }
94 }
95
96 var udpListenerTests = []struct {
97 network string
98 address string
99 }{
100 {"udp", ""},
101 {"udp", "0.0.0.0"},
102 {"udp", "::ffff:0.0.0.0"},
103 {"udp", "::"},
104
105 {"udp", "127.0.0.1"},
106 {"udp", "::ffff:127.0.0.1"},
107 {"udp", "::1"},
108
109 {"udp4", ""},
110 {"udp4", "0.0.0.0"},
111 {"udp4", "::ffff:0.0.0.0"},
112
113 {"udp4", "127.0.0.1"},
114 {"udp4", "::ffff:127.0.0.1"},
115
116 {"udp6", ""},
117 {"udp6", "::"},
118
119 {"udp6", "::1"},
120 }
121
122
123
124
125 func TestUDPListener(t *testing.T) {
126 switch runtime.GOOS {
127 case "plan9":
128 t.Skipf("not supported on %s", runtime.GOOS)
129 }
130
131 for _, tt := range udpListenerTests {
132 if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
133 t.Logf("skipping %s test", tt.network+" "+tt.address)
134 continue
135 }
136
137 c1, err := ListenPacket(tt.network, JoinHostPort(tt.address, "0"))
138 if err != nil {
139 t.Fatal(err)
140 }
141 if err := checkFirstListener(tt.network, c1); err != nil {
142 c1.Close()
143 t.Fatal(err)
144 }
145 c2, err := ListenPacket(tt.network, JoinHostPort(tt.address, c1.(*UDPConn).port()))
146 if err == nil {
147 c2.Close()
148 }
149 if err := checkSecondListener(tt.network, tt.address, err); err != nil {
150 c1.Close()
151 t.Fatal(err)
152 }
153 c1.Close()
154 }
155 }
156
157 var dualStackTCPListenerTests = []struct {
158 network1, address1 string
159 network2, address2 string
160 xerr error
161 }{
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 {"tcp", "", "tcp", "", syscall.EADDRINUSE},
197 {"tcp", "", "tcp", "0.0.0.0", syscall.EADDRINUSE},
198 {"tcp", "0.0.0.0", "tcp", "", syscall.EADDRINUSE},
199
200 {"tcp", "", "tcp", "::", syscall.EADDRINUSE},
201 {"tcp", "::", "tcp", "", syscall.EADDRINUSE},
202 {"tcp", "0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
203 {"tcp", "::", "tcp", "0.0.0.0", syscall.EADDRINUSE},
204 {"tcp", "::ffff:0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
205 {"tcp", "::", "tcp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
206
207 {"tcp4", "", "tcp6", "", nil},
208 {"tcp6", "", "tcp4", "", nil},
209 {"tcp4", "0.0.0.0", "tcp6", "::", nil},
210 {"tcp6", "::", "tcp4", "0.0.0.0", nil},
211
212 {"tcp", "127.0.0.1", "tcp", "::1", nil},
213 {"tcp", "::1", "tcp", "127.0.0.1", nil},
214 {"tcp4", "127.0.0.1", "tcp6", "::1", nil},
215 {"tcp6", "::1", "tcp4", "127.0.0.1", nil},
216 }
217
218
219
220
221
222
223
224 func TestDualStackTCPListener(t *testing.T) {
225 switch runtime.GOOS {
226 case "plan9":
227 t.Skipf("not supported on %s", runtime.GOOS)
228 }
229 if !supportsIPv4() || !supportsIPv6() {
230 t.Skip("both IPv4 and IPv6 are required")
231 }
232
233 for _, tt := range dualStackTCPListenerTests {
234 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
235 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
236 continue
237 }
238
239 if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
240 tt.xerr = nil
241 }
242 var firstErr, secondErr error
243 for i := 0; i < 5; i++ {
244 lns, err := newDualStackListener()
245 if err != nil {
246 t.Fatal(err)
247 }
248 port := lns[0].port()
249 for _, ln := range lns {
250 ln.Close()
251 }
252 var ln1 Listener
253 ln1, firstErr = Listen(tt.network1, JoinHostPort(tt.address1, port))
254 if firstErr != nil {
255 continue
256 }
257 if err := checkFirstListener(tt.network1, ln1); err != nil {
258 ln1.Close()
259 t.Fatal(err)
260 }
261 ln2, err := Listen(tt.network2, JoinHostPort(tt.address2, ln1.(*TCPListener).port()))
262 if err == nil {
263 ln2.Close()
264 }
265 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
266 ln1.Close()
267 continue
268 }
269 ln1.Close()
270 break
271 }
272 if firstErr != nil {
273 t.Error(firstErr)
274 }
275 if secondErr != nil {
276 t.Error(secondErr)
277 }
278 }
279 }
280
281 var dualStackUDPListenerTests = []struct {
282 network1, address1 string
283 network2, address2 string
284 xerr error
285 }{
286 {"udp", "", "udp", "", syscall.EADDRINUSE},
287 {"udp", "", "udp", "0.0.0.0", syscall.EADDRINUSE},
288 {"udp", "0.0.0.0", "udp", "", syscall.EADDRINUSE},
289
290 {"udp", "", "udp", "::", syscall.EADDRINUSE},
291 {"udp", "::", "udp", "", syscall.EADDRINUSE},
292 {"udp", "0.0.0.0", "udp", "::", syscall.EADDRINUSE},
293 {"udp", "::", "udp", "0.0.0.0", syscall.EADDRINUSE},
294 {"udp", "::ffff:0.0.0.0", "udp", "::", syscall.EADDRINUSE},
295 {"udp", "::", "udp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
296
297 {"udp4", "", "udp6", "", nil},
298 {"udp6", "", "udp4", "", nil},
299 {"udp4", "0.0.0.0", "udp6", "::", nil},
300 {"udp6", "::", "udp4", "0.0.0.0", nil},
301
302 {"udp", "127.0.0.1", "udp", "::1", nil},
303 {"udp", "::1", "udp", "127.0.0.1", nil},
304 {"udp4", "127.0.0.1", "udp6", "::1", nil},
305 {"udp6", "::1", "udp4", "127.0.0.1", nil},
306 }
307
308
309
310
311
312
313
314 func TestDualStackUDPListener(t *testing.T) {
315 switch runtime.GOOS {
316 case "plan9":
317 t.Skipf("not supported on %s", runtime.GOOS)
318 }
319 if !supportsIPv4() || !supportsIPv6() {
320 t.Skip("both IPv4 and IPv6 are required")
321 }
322
323 for _, tt := range dualStackUDPListenerTests {
324 if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
325 t.Logf("skipping %s test", tt.network1+" "+tt.address1)
326 continue
327 }
328
329 if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
330 tt.xerr = nil
331 }
332 var firstErr, secondErr error
333 for i := 0; i < 5; i++ {
334 cs, err := newDualStackPacketListener()
335 if err != nil {
336 t.Fatal(err)
337 }
338 port := cs[0].port()
339 for _, c := range cs {
340 c.Close()
341 }
342 var c1 PacketConn
343 c1, firstErr = ListenPacket(tt.network1, JoinHostPort(tt.address1, port))
344 if firstErr != nil {
345 continue
346 }
347 if err := checkFirstListener(tt.network1, c1); err != nil {
348 c1.Close()
349 t.Fatal(err)
350 }
351 c2, err := ListenPacket(tt.network2, JoinHostPort(tt.address2, c1.(*UDPConn).port()))
352 if err == nil {
353 c2.Close()
354 }
355 if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
356 c1.Close()
357 continue
358 }
359 c1.Close()
360 break
361 }
362 if firstErr != nil {
363 t.Error(firstErr)
364 }
365 if secondErr != nil {
366 t.Error(secondErr)
367 }
368 }
369 }
370
371 func differentWildcardAddr(i, j string) bool {
372 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") {
373 return false
374 }
375 if i == "[::]" && j == "[::]" {
376 return false
377 }
378 return true
379 }
380
381 func checkFirstListener(network string, ln any) error {
382 switch network {
383 case "tcp":
384 fd := ln.(*TCPListener).fd
385 if err := checkDualStackAddrFamily(fd); err != nil {
386 return err
387 }
388 case "tcp4":
389 fd := ln.(*TCPListener).fd
390 if fd.family != syscall.AF_INET {
391 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
392 }
393 case "tcp6":
394 fd := ln.(*TCPListener).fd
395 if fd.family != syscall.AF_INET6 {
396 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
397 }
398 case "udp":
399 fd := ln.(*UDPConn).fd
400 if err := checkDualStackAddrFamily(fd); err != nil {
401 return err
402 }
403 case "udp4":
404 fd := ln.(*UDPConn).fd
405 if fd.family != syscall.AF_INET {
406 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
407 }
408 case "udp6":
409 fd := ln.(*UDPConn).fd
410 if fd.family != syscall.AF_INET6 {
411 return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
412 }
413 default:
414 return UnknownNetworkError(network)
415 }
416 return nil
417 }
418
419 func checkSecondListener(network, address string, err error) error {
420 switch network {
421 case "tcp", "tcp4", "tcp6":
422 if err == nil {
423 return fmt.Errorf("%s should fail", network+" "+address)
424 }
425 case "udp", "udp4", "udp6":
426 if err == nil {
427 return fmt.Errorf("%s should fail", network+" "+address)
428 }
429 default:
430 return UnknownNetworkError(network)
431 }
432 return nil
433 }
434
435 func checkDualStackSecondListener(network, address string, err, xerr error) error {
436 switch network {
437 case "tcp", "tcp4", "tcp6":
438 if xerr == nil && err != nil || xerr != nil && err == nil {
439 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
440 }
441 case "udp", "udp4", "udp6":
442 if xerr == nil && err != nil || xerr != nil && err == nil {
443 return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
444 }
445 default:
446 return UnknownNetworkError(network)
447 }
448 return nil
449 }
450
451 func checkDualStackAddrFamily(fd *netFD) error {
452 switch a := fd.laddr.(type) {
453 case *TCPAddr:
454
455
456
457
458 if supportsIPv4map() && fd.laddr.(*TCPAddr).isWildcard() {
459 if fd.family != syscall.AF_INET6 {
460 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
461 }
462 } else {
463 if fd.family != a.family() {
464 return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
465 }
466 }
467 case *UDPAddr:
468
469
470
471
472 if supportsIPv4map() && fd.laddr.(*UDPAddr).isWildcard() {
473 if fd.family != syscall.AF_INET6 {
474 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
475 }
476 } else {
477 if fd.family != a.family() {
478 return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
479 }
480 }
481 default:
482 return fmt.Errorf("unexpected protocol address type: %T", a)
483 }
484 return nil
485 }
486
487 func TestWildWildcardListener(t *testing.T) {
488 testenv.MustHaveExternalNetwork(t)
489
490 switch runtime.GOOS {
491 case "plan9":
492 t.Skipf("not supported on %s", runtime.GOOS)
493 }
494
495 defer func() {
496 if p := recover(); p != nil {
497 t.Fatalf("panicked: %v", p)
498 }
499 }()
500
501 if ln, err := Listen("tcp", ""); err == nil {
502 ln.Close()
503 }
504 if ln, err := ListenPacket("udp", ""); err == nil {
505 ln.Close()
506 }
507 if ln, err := ListenTCP("tcp", nil); err == nil {
508 ln.Close()
509 }
510 if ln, err := ListenUDP("udp", nil); err == nil {
511 ln.Close()
512 }
513 if ln, err := ListenIP("ip:icmp", nil); err == nil {
514 ln.Close()
515 }
516 }
517
518 var ipv4MulticastListenerTests = []struct {
519 net string
520 gaddr *UDPAddr
521 }{
522 {"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
523
524 {"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
525 }
526
527
528
529
530 func TestIPv4MulticastListener(t *testing.T) {
531 testenv.MustHaveExternalNetwork(t)
532
533 switch runtime.GOOS {
534 case "android", "plan9":
535 t.Skipf("not supported on %s", runtime.GOOS)
536 }
537 if !supportsIPv4() {
538 t.Skip("IPv4 is not supported")
539 }
540
541 closer := func(cs []*UDPConn) {
542 for _, c := range cs {
543 if c != nil {
544 c.Close()
545 }
546 }
547 }
548
549 for _, ifi := range []*Interface{loopbackInterface(), nil} {
550
551
552
553
554
555 if ifi == nil || !*testIPv4 {
556 continue
557 }
558 for _, tt := range ipv4MulticastListenerTests {
559 var err error
560 cs := make([]*UDPConn, 2)
561 if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
562 t.Fatal(err)
563 }
564 if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
565 closer(cs)
566 t.Fatal(err)
567 }
568 if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
569 closer(cs)
570 t.Fatal(err)
571 }
572 if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
573 closer(cs)
574 t.Fatal(err)
575 }
576 closer(cs)
577 }
578 }
579 }
580
581 var ipv6MulticastListenerTests = []struct {
582 net string
583 gaddr *UDPAddr
584 }{
585 {"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
586 {"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
587 {"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
588 {"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
589 {"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
590 {"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
591
592 {"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
593 {"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
594 {"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
595 {"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
596 {"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
597 {"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
598 }
599
600
601
602
603 func TestIPv6MulticastListener(t *testing.T) {
604 testenv.MustHaveExternalNetwork(t)
605
606 switch runtime.GOOS {
607 case "plan9":
608 t.Skipf("not supported on %s", runtime.GOOS)
609 }
610 if !supportsIPv6() {
611 t.Skip("IPv6 is not supported")
612 }
613
614 if runtime.GOOS != "windows" && 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":
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, &ListenConfig{Control: controlOnConnSetup})
739 ln.Close()
740 }
741 })
742 t.Run("PacketListen", func(t *testing.T) {
743 for _, network := range []string{"udp", "udp4", "udp6", "unixgram"} {
744 if !testableNetwork(network) {
745 continue
746 }
747 c := newLocalPacketListener(t, network, &ListenConfig{Control: controlOnConnSetup})
748 c.Close()
749 }
750 })
751 }
752
View as plain text