Source file
src/net/udpsock_test.go
1
2
3
4
5 package net
6
7 import (
8 "errors"
9 "fmt"
10 "internal/asan"
11 "internal/race"
12 "internal/testenv"
13 "net/netip"
14 "os"
15 "reflect"
16 "runtime"
17 "testing"
18 "time"
19 )
20
21 func BenchmarkUDP6LinkLocalUnicast(b *testing.B) {
22 testHookUninstaller.Do(uninstallTestHooks)
23
24 if !supportsIPv6() {
25 b.Skip("IPv6 is not supported")
26 }
27 ifi := loopbackInterface()
28 if ifi == nil {
29 b.Skip("loopback interface not found")
30 }
31 lla := ipv6LinkLocalUnicastAddr(ifi)
32 if lla == "" {
33 b.Skip("IPv6 link-local unicast address not found")
34 }
35
36 c1, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0"))
37 if err != nil {
38 b.Fatal(err)
39 }
40 defer c1.Close()
41 c2, err := ListenPacket("udp6", JoinHostPort(lla+"%"+ifi.Name, "0"))
42 if err != nil {
43 b.Fatal(err)
44 }
45 defer c2.Close()
46
47 var buf [1]byte
48 for i := 0; i < b.N; i++ {
49 if _, err := c1.WriteTo(buf[:], c2.LocalAddr()); err != nil {
50 b.Fatal(err)
51 }
52 if _, _, err := c2.ReadFrom(buf[:]); err != nil {
53 b.Fatal(err)
54 }
55 }
56 }
57
58 type resolveUDPAddrTest struct {
59 network string
60 litAddrOrName string
61 addr *UDPAddr
62 err error
63 }
64
65 var resolveUDPAddrTests = []resolveUDPAddrTest{
66 {"udp", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
67 {"udp4", "127.0.0.1:65535", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 65535}, nil},
68
69 {"udp", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
70 {"udp6", "[::1]:65535", &UDPAddr{IP: ParseIP("::1"), Port: 65535}, nil},
71
72 {"udp", "[::1%en0]:1", &UDPAddr{IP: ParseIP("::1"), Port: 1, Zone: "en0"}, nil},
73 {"udp6", "[::1%911]:2", &UDPAddr{IP: ParseIP("::1"), Port: 2, Zone: "911"}, nil},
74
75 {"", "127.0.0.1:0", &UDPAddr{IP: IPv4(127, 0, 0, 1), Port: 0}, nil},
76 {"", "[::1]:0", &UDPAddr{IP: ParseIP("::1"), Port: 0}, nil},
77
78 {"udp", ":12345", &UDPAddr{Port: 12345}, nil},
79
80 {"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
81
82 {"udp", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
83 {"udp", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 53}, nil},
84 {"udp", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
85 {"udp4", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
86 {"udp4", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
87 {"udp6", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
88
89 {"udp4", "[2001:db8::1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
90 {"udp6", "127.0.0.1:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
91 {"udp6", "[::ffff:127.0.0.1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
92 }
93
94 func TestResolveUDPAddr(t *testing.T) {
95 origTestHookLookupIP := testHookLookupIP
96 defer func() { testHookLookupIP = origTestHookLookupIP }()
97 testHookLookupIP = lookupLocalhost
98
99 for _, tt := range resolveUDPAddrTests {
100 addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName)
101 if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
102 t.Errorf("ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
103 continue
104 }
105 if err == nil {
106 addr2, err := ResolveUDPAddr(addr.Network(), addr.String())
107 if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
108 t.Errorf("(%q, %q): ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
109 }
110 }
111 }
112 }
113
114 func TestWriteToUDP(t *testing.T) {
115 switch runtime.GOOS {
116 case "plan9":
117 t.Skipf("not supported on %s", runtime.GOOS)
118 }
119
120 for _, network := range []string{"udp4", "udp6"} {
121 t.Run(network, func(t *testing.T) {
122 if !testableNetwork(network) {
123 t.Skipf("skipping: %s not supported", network)
124 }
125
126 c, err := ListenPacket(network, JoinHostPort(loopbackIP(network).String(), "0"))
127 if err != nil {
128 t.Fatal(err)
129 }
130 defer c.Close()
131
132 testWriteToConn(t, network, c.LocalAddr().String())
133 testWriteToPacketConn(t, network, c.LocalAddr().String())
134 })
135 }
136 }
137
138 func testWriteToConn(t *testing.T, network, raddr string) {
139 c, err := Dial(network, raddr)
140 if err != nil {
141 t.Fatal(err)
142 }
143 defer c.Close()
144
145 ra, err := ResolveUDPAddr(network, raddr)
146 if err != nil {
147 t.Fatal(err)
148 }
149 rap := ra.AddrPort()
150
151 assertErrWriteToConnected := func(t *testing.T, err error) {
152 t.Helper()
153 if e, ok := err.(*OpError); !ok || e.Err != ErrWriteToConnected {
154 t.Errorf("got %v; want ErrWriteToConnected", err)
155 }
156 }
157
158 b := []byte("CONNECTED-MODE SOCKET")
159 _, err = c.(*UDPConn).WriteToUDPAddrPort(b, rap)
160 assertErrWriteToConnected(t, err)
161 _, err = c.(*UDPConn).WriteToUDP(b, ra)
162 assertErrWriteToConnected(t, err)
163 _, err = c.(*UDPConn).WriteTo(b, ra)
164 assertErrWriteToConnected(t, err)
165 _, err = c.Write(b)
166 if err != nil {
167 t.Errorf("c.Write(b) = %v; want nil", err)
168 }
169 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
170 assertErrWriteToConnected(t, err)
171 n, oobn, err := c.(*UDPConn).WriteMsgUDP(b, nil, nil)
172 if err != nil {
173 t.Errorf("c.WriteMsgUDP(b, nil, nil) = %v; want nil", err)
174 }
175 if n != len(b) || oobn != 0 {
176 t.Errorf("c.WriteMsgUDP(b, nil, nil) = %d, %d; want %d, 0", n, oobn, len(b))
177 }
178 _, _, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, rap)
179 assertErrWriteToConnected(t, err)
180 n, oobn, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, netip.AddrPort{})
181 if err != nil {
182 t.Errorf("c.WriteMsgUDPAddrPort(b, nil, netip.AddrPort{}) = %v; want nil", err)
183 }
184 if n != len(b) || oobn != 0 {
185 t.Errorf("c.WriteMsgUDPAddrPort(b, nil, netip.AddrPort{}) = %d, %d; want %d, 0", n, oobn, len(b))
186 }
187 }
188
189 func testWriteToPacketConn(t *testing.T, network, raddr string) {
190 c, err := ListenPacket(network, JoinHostPort(loopbackIP(network).String(), "0"))
191 if err != nil {
192 t.Fatal(err)
193 }
194 defer c.Close()
195
196 ra, err := ResolveUDPAddr(network, raddr)
197 if err != nil {
198 t.Fatal(err)
199 }
200
201 b := []byte("UNCONNECTED-MODE SOCKET")
202 _, err = c.(*UDPConn).WriteToUDP(b, ra)
203 if err != nil {
204 t.Fatal(err)
205 }
206 _, err = c.WriteTo(b, ra)
207 if err != nil {
208 t.Fatal(err)
209 }
210 _, err = c.(*UDPConn).Write(b)
211 if err == nil {
212 t.Fatal("should fail")
213 }
214 _, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
215 if err == nil {
216 t.Fatal("should fail")
217 }
218 if err != nil && err.(*OpError).Err != errMissingAddress {
219 t.Fatalf("should fail as errMissingAddress: %v", err)
220 }
221 n, oobn, err := c.(*UDPConn).WriteMsgUDP(b, nil, ra)
222 if err != nil {
223 t.Fatal(err)
224 }
225 if n != len(b) || oobn != 0 {
226 t.Errorf("c.WriteMsgUDP(b, nil, ra) = %d, %d; want %d, 0", n, oobn, len(b))
227 }
228 n, oobn, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, ra.AddrPort())
229 if err != nil {
230 t.Fatal(err)
231 }
232 if n != len(b) || oobn != 0 {
233 t.Errorf("c.WriteMsgUDPAddrPort(b, nil, ra.AddrPort()) = %d, %d; want %d, 0", n, oobn, len(b))
234 }
235 }
236
237 var udpConnLocalNameTests = []struct {
238 net string
239 laddr *UDPAddr
240 }{
241 {"udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)}},
242 {"udp4", &UDPAddr{}},
243 {"udp4", nil},
244 }
245
246 func TestUDPConnLocalName(t *testing.T) {
247 testenv.MustHaveExternalNetwork(t)
248
249 for _, tt := range udpConnLocalNameTests {
250 t.Run(fmt.Sprint(tt.laddr), func(t *testing.T) {
251 if !testableNetwork(tt.net) {
252 t.Skipf("skipping: %s not available", tt.net)
253 }
254
255 c, err := ListenUDP(tt.net, tt.laddr)
256 if err != nil {
257 t.Fatal(err)
258 }
259 defer c.Close()
260 la := c.LocalAddr()
261 if a, ok := la.(*UDPAddr); !ok || a.Port == 0 {
262 t.Fatalf("got %v; expected a proper address with non-zero port number", la)
263 }
264 })
265 }
266 }
267
268 func TestUDPConnLocalAndRemoteNames(t *testing.T) {
269 if !testableNetwork("udp") {
270 t.Skipf("skipping: udp not available")
271 }
272
273 for _, laddr := range []string{"", "127.0.0.1:0"} {
274 c1, err := ListenPacket("udp", "127.0.0.1:0")
275 if err != nil {
276 t.Fatal(err)
277 }
278 defer c1.Close()
279
280 var la *UDPAddr
281 if laddr != "" {
282 var err error
283 if la, err = ResolveUDPAddr("udp", laddr); err != nil {
284 t.Fatal(err)
285 }
286 }
287 c2, err := DialUDP("udp", la, c1.LocalAddr().(*UDPAddr))
288 if err != nil {
289 t.Fatal(err)
290 }
291 defer c2.Close()
292
293 var connAddrs = [4]struct {
294 got Addr
295 ok bool
296 }{
297 {c1.LocalAddr(), true},
298 {c1.(*UDPConn).RemoteAddr(), false},
299 {c2.LocalAddr(), true},
300 {c2.RemoteAddr(), true},
301 }
302 for _, ca := range connAddrs {
303 if a, ok := ca.got.(*UDPAddr); ok != ca.ok || ok && a.Port == 0 {
304 t.Fatalf("got %v; expected a proper address with non-zero port number", ca.got)
305 }
306 }
307 }
308 }
309
310 func TestIPv6LinkLocalUnicastUDP(t *testing.T) {
311 testenv.MustHaveExternalNetwork(t)
312
313 if !supportsIPv6() {
314 t.Skip("IPv6 is not supported")
315 }
316
317 for i, tt := range ipv6LinkLocalUnicastUDPTests {
318 c1, err := ListenPacket(tt.network, tt.address)
319 if err != nil {
320
321
322 t.Log(err)
323 continue
324 }
325 ls := (&packetListener{PacketConn: c1}).newLocalServer()
326 defer ls.teardown()
327 ch := make(chan error, 1)
328 handler := func(ls *localPacketServer, c PacketConn) { packetTransponder(c, ch) }
329 if err := ls.buildup(handler); err != nil {
330 t.Fatal(err)
331 }
332 if la, ok := c1.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
333 t.Fatalf("got %v; expected a proper address with zone identifier", la)
334 }
335
336 c2, err := Dial(tt.network, ls.PacketConn.LocalAddr().String())
337 if err != nil {
338 t.Fatal(err)
339 }
340 defer c2.Close()
341 if la, ok := c2.LocalAddr().(*UDPAddr); !ok || !tt.nameLookup && la.Zone == "" {
342 t.Fatalf("got %v; expected a proper address with zone identifier", la)
343 }
344 if ra, ok := c2.RemoteAddr().(*UDPAddr); !ok || !tt.nameLookup && ra.Zone == "" {
345 t.Fatalf("got %v; expected a proper address with zone identifier", ra)
346 }
347
348 if _, err := c2.Write([]byte("UDP OVER IPV6 LINKLOCAL TEST")); err != nil {
349 t.Fatal(err)
350 }
351 b := make([]byte, 32)
352 if _, err := c2.Read(b); err != nil {
353 t.Fatal(err)
354 }
355
356 for err := range ch {
357 t.Errorf("#%d: %v", i, err)
358 }
359 }
360 }
361
362 func TestUDPZeroBytePayload(t *testing.T) {
363 switch runtime.GOOS {
364 case "plan9":
365 t.Skipf("not supported on %s", runtime.GOOS)
366 case "ios":
367 testenv.SkipFlaky(t, 29225)
368 }
369 if !testableNetwork("udp") {
370 t.Skipf("skipping: udp not available")
371 }
372
373 c := newLocalPacketListener(t, "udp")
374 defer c.Close()
375
376 for _, genericRead := range []bool{false, true} {
377 n, err := c.WriteTo(nil, c.LocalAddr())
378 if err != nil {
379 t.Fatal(err)
380 }
381 if n != 0 {
382 t.Errorf("got %d; want 0", n)
383 }
384 c.SetReadDeadline(time.Now().Add(30 * time.Second))
385 var b [1]byte
386 var name string
387 if genericRead {
388 _, err = c.(Conn).Read(b[:])
389 name = "Read"
390 } else {
391 _, _, err = c.ReadFrom(b[:])
392 name = "ReadFrom"
393 }
394 if err != nil {
395 t.Errorf("%s of zero byte packet failed: %v", name, err)
396 }
397 }
398 }
399
400 func TestUDPZeroByteBuffer(t *testing.T) {
401 switch runtime.GOOS {
402 case "plan9":
403 t.Skipf("not supported on %s", runtime.GOOS)
404 }
405 if !testableNetwork("udp") {
406 t.Skipf("skipping: udp not available")
407 }
408
409 c := newLocalPacketListener(t, "udp")
410 defer c.Close()
411
412 b := []byte("UDP ZERO BYTE BUFFER TEST")
413 for _, genericRead := range []bool{false, true} {
414 n, err := c.WriteTo(b, c.LocalAddr())
415 if err != nil {
416 t.Fatal(err)
417 }
418 if n != len(b) {
419 t.Errorf("got %d; want %d", n, len(b))
420 }
421 c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
422 if genericRead {
423 _, err = c.(Conn).Read(nil)
424 } else {
425 _, _, err = c.ReadFrom(nil)
426 }
427 switch err {
428 case nil:
429 default:
430 if nerr, ok := err.(Error); (!ok || !nerr.Timeout()) && runtime.GOOS != "windows" {
431 t.Fatal(err)
432 }
433 }
434 }
435 }
436
437 func TestUDPReadSizeError(t *testing.T) {
438 switch runtime.GOOS {
439 case "plan9":
440 t.Skipf("not supported on %s", runtime.GOOS)
441 }
442 if !testableNetwork("udp") {
443 t.Skipf("skipping: udp not available")
444 }
445
446 c1 := newLocalPacketListener(t, "udp")
447 defer c1.Close()
448
449 c2, err := Dial("udp", c1.LocalAddr().String())
450 if err != nil {
451 t.Fatal(err)
452 }
453 defer c2.Close()
454
455 b1 := []byte("READ SIZE ERROR TEST")
456 for _, genericRead := range []bool{false, true} {
457 n, err := c2.Write(b1)
458 if err != nil {
459 t.Fatal(err)
460 }
461 if n != len(b1) {
462 t.Errorf("got %d; want %d", n, len(b1))
463 }
464 b2 := make([]byte, len(b1)-1)
465 if genericRead {
466 n, err = c1.(Conn).Read(b2)
467 } else {
468 n, _, err = c1.ReadFrom(b2)
469 }
470 if err != nil && runtime.GOOS != "windows" {
471 t.Fatal(err)
472 }
473 if n != len(b1)-1 {
474 t.Fatalf("got %d; want %d", n, len(b1)-1)
475 }
476 }
477 }
478
479
480
481 func TestUDPReadTimeout(t *testing.T) {
482 if !testableNetwork("udp4") {
483 t.Skipf("skipping: udp4 not available")
484 }
485
486 la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
487 if err != nil {
488 t.Fatal(err)
489 }
490 c, err := ListenUDP("udp4", la)
491 if err != nil {
492 t.Fatal(err)
493 }
494 defer c.Close()
495
496 c.SetDeadline(time.Now())
497 b := make([]byte, 1)
498 n, addr, err := c.ReadFromUDP(b)
499 if !errors.Is(err, os.ErrDeadlineExceeded) {
500 t.Errorf("ReadFromUDP got err %v want os.ErrDeadlineExceeded", err)
501 }
502 if n != 0 {
503 t.Errorf("ReadFromUDP got n %d want 0", n)
504 }
505 if addr != nil {
506 t.Errorf("ReadFromUDP got addr %+#v want nil", addr)
507 }
508 }
509
510 func TestAllocs(t *testing.T) {
511 switch runtime.GOOS {
512 case "plan9", "js", "wasip1":
513
514 t.Skipf("skipping on %v", runtime.GOOS)
515 case "windows":
516 if race.Enabled {
517
518
519 t.Skip("skipping test in race")
520 }
521 }
522 if !testableNetwork("udp4") {
523 t.Skipf("skipping: udp4 not available")
524 }
525 if asan.Enabled {
526 t.Skip("test allocates more with -asan; see #70079")
527 }
528
529
530 testenv.SkipIfOptimizationOff(t)
531
532 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
533 if err != nil {
534 t.Fatal(err)
535 }
536 defer conn.Close()
537 addr := conn.LocalAddr()
538 addrPort := addr.(*UDPAddr).AddrPort()
539 buf := make([]byte, 8)
540
541 allocs := testing.AllocsPerRun(1000, func() {
542 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addrPort)
543 if err != nil {
544 t.Fatal(err)
545 }
546 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil)
547 if err != nil {
548 t.Fatal(err)
549 }
550 })
551 if got := int(allocs); got != 0 {
552 t.Errorf("WriteMsgUDPAddrPort/ReadMsgUDPAddrPort allocated %d objects", got)
553 }
554
555 allocs = testing.AllocsPerRun(1000, func() {
556 _, err := conn.WriteToUDPAddrPort(buf, addrPort)
557 if err != nil {
558 t.Fatal(err)
559 }
560 _, _, err = conn.ReadFromUDPAddrPort(buf)
561 if err != nil {
562 t.Fatal(err)
563 }
564 })
565 if got := int(allocs); got != 0 {
566 t.Errorf("WriteToUDPAddrPort/ReadFromUDPAddrPort allocated %d objects", got)
567 }
568
569 allocs = testing.AllocsPerRun(1000, func() {
570 _, err := conn.WriteTo(buf, addr)
571 if err != nil {
572 t.Fatal(err)
573 }
574 _, _, err = conn.ReadFromUDP(buf)
575 if err != nil {
576 t.Fatal(err)
577 }
578 })
579 if got := int(allocs); got != 1 {
580 t.Errorf("WriteTo/ReadFromUDP allocated %d objects", got)
581 }
582 }
583
584 func BenchmarkReadWriteMsgUDPAddrPort(b *testing.B) {
585 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
586 if err != nil {
587 b.Fatal(err)
588 }
589 defer conn.Close()
590 addr := conn.LocalAddr().(*UDPAddr).AddrPort()
591 buf := make([]byte, 8)
592 b.ResetTimer()
593 b.ReportAllocs()
594 for i := 0; i < b.N; i++ {
595 _, _, err := conn.WriteMsgUDPAddrPort(buf, nil, addr)
596 if err != nil {
597 b.Fatal(err)
598 }
599 _, _, _, _, err = conn.ReadMsgUDPAddrPort(buf, nil)
600 if err != nil {
601 b.Fatal(err)
602 }
603 }
604 }
605
606 func BenchmarkWriteToReadFromUDP(b *testing.B) {
607 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
608 if err != nil {
609 b.Fatal(err)
610 }
611 defer conn.Close()
612 addr := conn.LocalAddr()
613 buf := make([]byte, 8)
614 b.ResetTimer()
615 b.ReportAllocs()
616 for i := 0; i < b.N; i++ {
617 _, err := conn.WriteTo(buf, addr)
618 if err != nil {
619 b.Fatal(err)
620 }
621 _, _, err = conn.ReadFromUDP(buf)
622 if err != nil {
623 b.Fatal(err)
624 }
625 }
626 }
627
628 func BenchmarkWriteToReadFromUDPAddrPort(b *testing.B) {
629 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
630 if err != nil {
631 b.Fatal(err)
632 }
633 defer conn.Close()
634 addr := conn.LocalAddr().(*UDPAddr).AddrPort()
635 buf := make([]byte, 8)
636 b.ResetTimer()
637 b.ReportAllocs()
638 for i := 0; i < b.N; i++ {
639 _, err := conn.WriteToUDPAddrPort(buf, addr)
640 if err != nil {
641 b.Fatal(err)
642 }
643 _, _, err = conn.ReadFromUDPAddrPort(buf)
644 if err != nil {
645 b.Fatal(err)
646 }
647 }
648 }
649
650 func TestUDPIPVersionReadMsg(t *testing.T) {
651 switch runtime.GOOS {
652 case "plan9":
653 t.Skipf("skipping on %v", runtime.GOOS)
654 }
655 if !testableNetwork("udp4") {
656 t.Skipf("skipping: udp4 not available")
657 }
658
659 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
660 if err != nil {
661 t.Fatal(err)
662 }
663 defer conn.Close()
664 daddr := conn.LocalAddr().(*UDPAddr).AddrPort()
665 buf := make([]byte, 8)
666 _, err = conn.WriteToUDPAddrPort(buf, daddr)
667 if err != nil {
668 t.Fatal(err)
669 }
670 _, _, _, saddr, err := conn.ReadMsgUDPAddrPort(buf, nil)
671 if err != nil {
672 t.Fatal(err)
673 }
674 if !saddr.Addr().Is4() {
675 t.Error("returned AddrPort is not IPv4")
676 }
677 _, err = conn.WriteToUDPAddrPort(buf, daddr)
678 if err != nil {
679 t.Fatal(err)
680 }
681 _, _, _, soldaddr, err := conn.ReadMsgUDP(buf, nil)
682 if err != nil {
683 t.Fatal(err)
684 }
685 if len(soldaddr.IP) != 4 {
686 t.Error("returned UDPAddr is not IPv4")
687 }
688 }
689
690
691
692
693 func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
694 if !testableNetwork("udp4") {
695 t.Skipf("skipping: udp4 not available")
696 }
697 if !testableNetwork("udp6") {
698 t.Skipf("skipping: udp6 not available")
699 }
700
701 switch runtime.GOOS {
702 case "dragonfly", "openbsd":
703
704
705
706
707 t.Skipf("skipping on %v", runtime.GOOS)
708 }
709
710 conn, err := ListenUDP("udp", nil)
711 if err != nil {
712 t.Fatal(err)
713 }
714 defer conn.Close()
715
716 daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
717 daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
718 daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
719 buf := make([]byte, 8)
720
721 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4)
722 if err != nil {
723 t.Fatal(err)
724 }
725
726 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6)
727 if err != nil {
728 t.Fatal(err)
729 }
730
731 _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6)
732 if err != nil {
733 t.Fatal(err)
734 }
735 }
736
737
738
739
740 func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
741 switch runtime.GOOS {
742 case "plan9":
743 t.Skipf("not supported on %s", runtime.GOOS)
744 }
745
746 if !testableNetwork("udp4") {
747 t.Skipf("skipping: udp4 not available")
748 }
749
750 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
751 if err != nil {
752 t.Fatal(err)
753 }
754 defer conn.Close()
755
756 daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
757 daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
758 daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
759 buf := make([]byte, 8)
760
761 if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4); err != nil {
762 t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4) failed: %v", err)
763 }
764
765 if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6); err != nil {
766 t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) failed: %v", err)
767 }
768
769 if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6); err == nil {
770 t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error")
771 }
772 }
773
774
775
776
777
778
779 func TestReadWriteMsgUDPAddrPortEmptyCmsg(t *testing.T) {
780 switch runtime.GOOS {
781 case "plan9":
782 t.Skipf("not supported on %s", runtime.GOOS)
783 }
784
785 if !testableNetwork("udp4") {
786 t.Skipf("skipping: udp4 not available")
787 }
788
789 conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
790 if err != nil {
791 t.Fatal(err)
792 }
793 defer conn.Close()
794
795 buf := make([]byte, 8)
796 cmsgBuf := make([]byte, 8)[:0]
797 daddr := conn.LocalAddr().(*UDPAddr).AddrPort()
798
799 _, cmsgn, err := conn.WriteMsgUDPAddrPort(buf, cmsgBuf, daddr)
800 if err != nil {
801 t.Fatalf("WriteMsgUDPAddrPort failed: %v", err)
802 }
803 if cmsgn != 0 {
804 t.Errorf("WriteMsgUDPAddrPort wrote %d cmsg bytes; want 0", cmsgn)
805 }
806
807 _, cmsgn, _, _, err = conn.ReadMsgUDPAddrPort(buf, cmsgBuf)
808 if err != nil {
809 t.Fatalf("ReadMsgUDPAddrPort failed: %v", err)
810 }
811 if cmsgn != 0 {
812 t.Errorf("ReadMsgUDPAddrPort read %d cmsg bytes; want 0", cmsgn)
813 }
814 }
815
816
817
818 func TestDualStackUDPBroadcast(t *testing.T) {
819 switch runtime.GOOS {
820 case "plan9":
821 t.Skipf("not supported on %s", runtime.GOOS)
822 }
823 if !supportsIPv4map() {
824 t.Skip("dual-stack IPv6 sockets not supported")
825 }
826 mustHaveExternalNetwork(t)
827
828 conn, err := ListenUDP("udp", nil)
829 if err != nil {
830 t.Fatal(err)
831 }
832 defer conn.Close()
833
834 addr := netip.AddrPortFrom(netip.MustParseAddr("255.255.255.255"), 12345)
835 if _, err := conn.WriteToUDPAddrPort([]byte{0}, addr); err != nil {
836 if isUnreachableError(err) {
837 t.Skipf("broadcast route not available: %v", err)
838 }
839 t.Errorf("WriteToUDPAddrPort failed: %v", err)
840 }
841 }
842
View as plain text