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.
16 var multicastListenerTests
= []struct {
20 ipv6
bool // test with underlying AF_INET6 socket
22 // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
24 {"udp", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}, FlagUp | FlagLoopback
, false},
25 {"udp", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}, 0, false},
26 {"udp", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
27 {"udp", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}, 0, true},
29 {"udp4", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}, FlagUp | FlagLoopback
, false},
30 {"udp4", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}, 0, false},
32 {"udp6", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
33 {"udp6", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}, 0, true},
34 {"udp6", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
35 {"udp6", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}, 0, true},
36 {"udp6", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
37 {"udp6", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}, 0, true},
38 {"udp6", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
39 {"udp6", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}, 0, true},
40 {"udp6", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
41 {"udp6", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}, 0, true},
42 {"udp6", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}, FlagUp | FlagLoopback
, true},
43 {"udp6", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}, 0, true},
46 // TestMulticastListener tests both single and double listen to a test
47 // listener with same address family, same group address and same port.
48 func TestMulticastListener(t
*testing
.T
) {
50 case "netbsd", "openbsd", "plan9", "solaris", "windows":
51 t
.Skipf("skipping test on %q", runtime
.GOOS
)
53 if runtime
.GOARCH
== "arm" || runtime
.GOARCH
== "alpha" {
54 t
.Skipf("skipping test on %q/%q", runtime
.GOOS
, runtime
.GOARCH
)
58 for _
, tt
:= range multicastListenerTests
{
59 if tt
.ipv6
&& (!*testIPv6 ||
!supportsIPv6 || os
.Getuid() != 0) {
62 ifi
, err
:= availMulticastInterface(t
, tt
.flags
)
66 c1
, err
:= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
)
68 t
.Fatalf("First ListenMulticastUDP failed: %v", err
)
70 checkMulticastListener(t
, err
, c1
, tt
.gaddr
)
71 c2
, err
:= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
)
73 t
.Fatalf("Second ListenMulticastUDP failed: %v", err
)
75 checkMulticastListener(t
, err
, c2
, tt
.gaddr
)
81 func TestSimpleMulticastListener(t
*testing
.T
) {
84 t
.Skipf("skipping test on %q", runtime
.GOOS
)
86 if testing
.Short() ||
!*testExternal
{
87 t
.Skip("skipping test on windows to avoid firewall")
91 for _
, tt
:= range multicastListenerTests
{
95 tt
.flags
= FlagUp | FlagMulticast
// for windows testing
96 ifi
, err
:= availMulticastInterface(t
, tt
.flags
)
100 c1
, err
:= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
)
102 t
.Fatalf("First ListenMulticastUDP failed: %v", err
)
104 checkSimpleMulticastListener(t
, err
, c1
, tt
.gaddr
)
105 c2
, err
:= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
)
107 t
.Fatalf("Second ListenMulticastUDP failed: %v", err
)
109 checkSimpleMulticastListener(t
, err
, c2
, tt
.gaddr
)
115 func checkMulticastListener(t
*testing
.T
, err error
, c
*UDPConn
, gaddr
*UDPAddr
) {
116 if !multicastRIBContains(t
, gaddr
.IP
) {
117 t
.Errorf("%q not found in RIB", gaddr
.String())
122 t
.Error("LocalAddr failed")
125 if a
, ok
:= la
.(*UDPAddr
); !ok || a
.Port
== 0 {
126 t
.Errorf("got %v; expected a proper address with non-zero port number", la
)
131 func checkSimpleMulticastListener(t
*testing
.T
, err error
, c
*UDPConn
, gaddr
*UDPAddr
) {
134 t
.Error("LocalAddr failed")
137 if a
, ok
:= la
.(*UDPAddr
); !ok || a
.Port
== 0 {
138 t
.Errorf("got %v; expected a proper address with non-zero port number", la
)
143 func availMulticastInterface(t
*testing
.T
, flags Flags
) (*Interface
, error
) {
145 if flags
!= Flags(0) {
146 ift
, err
:= Interfaces()
148 t
.Fatalf("Interfaces failed: %v", err
)
150 for _
, x
:= range ift
{
151 if x
.Flags
&flags
== flags
{
157 return nil, errors
.New("an appropriate multicast interface not found")
163 func multicastRIBContains(t
*testing
.T
, ip IP
) bool {
164 ift
, err
:= Interfaces()
166 t
.Fatalf("Interfaces failed: %v", err
)
168 for _
, ifi
:= range ift
{
169 ifmat
, err
:= ifi
.MulticastAddrs()
171 t
.Fatalf("MulticastAddrs failed: %v", err
)
173 for _
, ifma
:= range ifmat
{
174 if ifma
.(*IPAddr
).IP
.Equal(ip
) {