LEFT | RIGHT |
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 package net | 1 package net |
6 | 2 |
7 import ( | 3 import ( |
| 4 "flag" |
8 "os" | 5 "os" |
9 "runtime" | 6 "runtime" |
10 "testing" | 7 "testing" |
11 ) | 8 ) |
12 | 9 |
13 var listenMulticastUDPTests = []struct { | 10 var multicast = flag.Bool("multicast", false, "enable multicast tests") |
| 11 |
| 12 var multicastUDPTests = []struct { |
14 net string | 13 net string |
15 » gaddr *UDPAddr | 14 » laddr IP |
| 15 » gaddr IP |
16 flags Flags | 16 flags Flags |
17 ipv6 bool | 17 ipv6 bool |
18 }{ | 18 }{ |
19 // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP,
and TCP Headers | 19 // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP,
and TCP Headers |
20 » {"udp", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, fa
lse}, | 20 » {"udp", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false}, |
21 » {"udp4", &UDPAddr{IPv4(224, 0, 0, 254), 12345}, FlagUp | FlagLoopback, f
alse}, | 21 » {"udp4", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false}
, |
22 » {"udp", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, tr
ue}, | 22 » {"udp", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback),
true}, |
23 » {"udp6", &UDPAddr{ParseIP("ff01::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 23 » {"udp6", IPv6unspecified, ParseIP("ff01::114"), (FlagUp | FlagLoopback),
true}, |
24 » {"udp6", &UDPAddr{ParseIP("ff02::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 24 » {"udp6", IPv6unspecified, ParseIP("ff02::114"), (FlagUp | FlagLoopback),
true}, |
25 » {"udp6", &UDPAddr{ParseIP("ff04::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 25 » {"udp6", IPv6unspecified, ParseIP("ff04::114"), (FlagUp | FlagLoopback),
true}, |
26 » {"udp6", &UDPAddr{ParseIP("ff05::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 26 » {"udp6", IPv6unspecified, ParseIP("ff05::114"), (FlagUp | FlagLoopback),
true}, |
27 » {"udp6", &UDPAddr{ParseIP("ff08::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 27 » {"udp6", IPv6unspecified, ParseIP("ff08::114"), (FlagUp | FlagLoopback),
true}, |
28 » {"udp6", &UDPAddr{ParseIP("ff0e::114"), 12345}, FlagUp | FlagLoopback, t
rue}, | 28 » {"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback),
true}, |
29 } | 29 } |
30 | 30 |
31 func TestListenMulticastUDP(t *testing.T) { | 31 func TestMulticastUDP(t *testing.T) { |
32 » switch runtime.GOOS { | 32 » if runtime.GOOS == "plan9" || runtime.GOOS == "windows" { |
33 » case "netbsd", "openbsd", "plan9", "windows": | 33 » » return |
| 34 » } |
| 35 » if !*multicast { |
| 36 » » t.Logf("test disabled; use --multicast to enable") |
34 return | 37 return |
35 } | 38 } |
36 | 39 |
37 » for _, tt := range listenMulticastUDPTests { | 40 » for _, tt := range multicastUDPTests { |
38 » » var ( | |
39 » » » ifi *Interface | |
40 » » » found bool | |
41 » » ) | |
42 if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) { | 41 if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) { |
43 continue | 42 continue |
44 } | 43 } |
45 ift, err := Interfaces() | |
46 if err != nil { | |
47 t.Fatalf("Interfaces failed: %v", err) | |
48 } | |
49 for _, x := range ift { | |
50 if x.Flags&tt.flags == tt.flags { | |
51 ifi = &x | |
52 break | |
53 } | |
54 } | |
55 if ifi == nil { | |
56 t.Logf("an appropriate multicast interface not found") | |
57 return | |
58 } | |
59 c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) | |
60 if err != nil { | |
61 t.Fatalf("ListenMulticastUDP failed: %v", err) | |
62 } | |
63 defer c.Close() // test to listen concurrently across multiple l
isteners | |
64 if !tt.ipv6 { | |
65 testIPv4MulticastSocketOptions(t, c.fd, ifi) | |
66 } else { | |
67 testIPv6MulticastSocketOptions(t, c.fd, ifi) | |
68 } | |
69 ifmat, err := ifi.MulticastAddrs() | |
70 if err != nil { | |
71 t.Fatalf("MulticastAddrs failed: %v", err) | |
72 } | |
73 for _, ifma := range ifmat { | |
74 if ifma.(*IPAddr).IP.Equal(tt.gaddr.IP) { | |
75 found = true | |
76 break | |
77 } | |
78 } | |
79 if !found { | |
80 t.Fatalf("%q not found in RIB", tt.gaddr.String()) | |
81 } | |
82 } | |
83 } | |
84 | |
85 func TestSimpleListenMulticastUDP(t *testing.T) { | |
86 switch runtime.GOOS { | |
87 case "plan9": | |
88 return | |
89 } | |
90 | |
91 for _, tt := range listenMulticastUDPTests { | |
92 var ifi *Interface | |
93 if tt.ipv6 { | |
94 continue | |
95 } | |
96 tt.flags = FlagUp | FlagMulticast | |
97 ift, err := Interfaces() | |
98 if err != nil { | |
99 t.Fatalf("Interfaces failed: %v", err) | |
100 } | |
101 for _, x := range ift { | |
102 if x.Flags&tt.flags == tt.flags { | |
103 ifi = &x | |
104 break | |
105 } | |
106 } | |
107 if ifi == nil { | |
108 t.Logf("an appropriate multicast interface not found") | |
109 return | |
110 } | |
111 c, err := ListenMulticastUDP(tt.net, ifi, tt.gaddr) | |
112 if err != nil { | |
113 t.Fatalf("ListenMulticastUDP failed: %v", err) | |
114 } | |
115 c.Close() | |
116 } | |
117 } | |
118 | |
119 func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) { | |
120 ifmc, err := ipv4MulticastInterface(fd) | |
121 if err != nil { | |
122 t.Fatalf("ipv4MulticastInterface failed: %v", err) | |
123 } | |
124 t.Logf("IPv4 multicast interface: %v", ifmc) | |
125 err = setIPv4MulticastInterface(fd, ifi) | |
126 if err != nil { | |
127 t.Fatalf("setIPv4MulticastInterface failed: %v", err) | |
128 } | |
129 | |
130 ttl, err := ipv4MulticastTTL(fd) | |
131 if err != nil { | |
132 t.Fatalf("ipv4MulticastTTL failed: %v", err) | |
133 } | |
134 t.Logf("IPv4 multicast TTL: %v", ttl) | |
135 err = setIPv4MulticastTTL(fd, 1) | |
136 if err != nil { | |
137 t.Fatalf("setIPv4MulticastTTL failed: %v", err) | |
138 } | |
139 | |
140 loop, err := ipv4MulticastLoopback(fd) | |
141 if err != nil { | |
142 t.Fatalf("ipv4MulticastLoopback failed: %v", err) | |
143 } | |
144 t.Logf("IPv4 multicast loopback: %v", loop) | |
145 err = setIPv4MulticastLoopback(fd, false) | |
146 if err != nil { | |
147 t.Fatalf("setIPv4MulticastLoopback failed: %v", err) | |
148 } | |
149 } | |
150 | |
151 func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) { | |
152 ifmc, err := ipv6MulticastInterface(fd) | |
153 if err != nil { | |
154 t.Fatalf("ipv6MulticastInterface failed: %v", err) | |
155 } | |
156 t.Logf("IPv6 multicast interface: %v", ifmc) | |
157 err = setIPv6MulticastInterface(fd, ifi) | |
158 if err != nil { | |
159 t.Fatalf("setIPv6MulticastInterface failed: %v", err) | |
160 } | |
161 | |
162 hoplim, err := ipv6MulticastHopLimit(fd) | |
163 if err != nil { | |
164 t.Fatalf("ipv6MulticastHopLimit failed: %v", err) | |
165 } | |
166 t.Logf("IPv6 multicast hop limit: %v", hoplim) | |
167 err = setIPv6MulticastHopLimit(fd, 1) | |
168 if err != nil { | |
169 t.Fatalf("setIPv6MulticastHopLimit failed: %v", err) | |
170 } | |
171 | |
172 loop, err := ipv6MulticastLoopback(fd) | |
173 if err != nil { | |
174 t.Fatalf("ipv6MulticastLoopback failed: %v", err) | |
175 } | |
176 t.Logf("IPv6 multicast loopback: %v", loop) | |
177 err = setIPv6MulticastLoopback(fd, false) | |
178 if err != nil { | |
179 t.Fatalf("setIPv6MulticastLoopback failed: %v", err) | |
180 } | |
181 } | |
LEFT | RIGHT |