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