Skip to content

Commit 10f1c90

Browse files
committed
wgengine/magicsock, types/nettype, etc: finish ReadFromUDPAddrPort netip migration
So we're staying within the netip.Addr/AddrPort consistently and avoiding allocs/conversions to the legacy net addr types. Updates tailscale#5162 Change-Id: I59feba60d3de39f773e68292d759766bac98c917 Signed-off-by: Brad Fitzpatrick <[email protected]>
1 parent 29f7df9 commit 10f1c90

File tree

8 files changed

+48
-54
lines changed

8 files changed

+48
-54
lines changed

net/dns/resolver/forwarder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ func (f *forwarder) sendUDP(ctx context.Context, fq *forwardQuery, rr resolverAn
521521

522522
// The 1 extra byte is to detect packet truncation.
523523
out := make([]byte, maxResponseBytes+1)
524-
n, _, err := conn.ReadFrom(out)
524+
n, _, err := conn.ReadFromUDPAddrPort(out)
525525
if err != nil {
526526
if err := ctx.Err(); err != nil {
527527
return nil, err

net/netcheck/netcheck.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ type Client struct {
208208
// reusing an existing UDP connection.
209209
type STUNConn interface {
210210
WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error)
211-
ReadFrom([]byte) (int, net.Addr, error)
211+
ReadFromUDPAddrPort([]byte) (int, netip.AddrPort, error)
212212
}
213213

214214
func (c *Client) enoughRegions() int {
@@ -518,7 +518,7 @@ func nodeMight4(n *tailcfg.DERPNode) bool {
518518
}
519519

520520
type packetReaderFromCloser interface {
521-
ReadFrom([]byte) (int, net.Addr, error)
521+
ReadFromUDPAddrPort([]byte) (int, netip.AddrPort, error)
522522
io.Closer
523523
}
524524

@@ -538,24 +538,19 @@ func (c *Client) readPackets(ctx context.Context, pc packetReaderFromCloser) {
538538

539539
var buf [64 << 10]byte
540540
for {
541-
n, addr, err := pc.ReadFrom(buf[:])
541+
n, addr, err := pc.ReadFromUDPAddrPort(buf[:])
542542
if err != nil {
543543
if ctx.Err() != nil {
544544
return
545545
}
546546
c.logf("ReadFrom: %v", err)
547547
return
548548
}
549-
ua, ok := addr.(*net.UDPAddr)
550-
if !ok {
551-
c.logf("ReadFrom: unexpected addr %T", addr)
552-
continue
553-
}
554549
pkt := buf[:n]
555550
if !stun.Is(pkt) {
556551
continue
557552
}
558-
if ap := netaddr.Unmap(ua.AddrPort()); ap.IsValid() {
553+
if ap := netaddr.Unmap(addr); ap.IsValid() {
559554
c.ReceiveSTUNPacket(pkt, ap)
560555
}
561556
}

net/portmapper/portmapper.go

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netip.AddrPor
531531

532532
res := make([]byte, 1500)
533533
for {
534-
n, srci, err := uc.ReadFrom(res)
534+
n, src, err := uc.ReadFromUDPAddrPort(res)
535535
if err != nil {
536536
if ctx.Err() == context.Canceled {
537537
return netip.AddrPort{}, err
@@ -542,8 +542,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netip.AddrPor
542542
}
543543
return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices}
544544
}
545-
srcu := srci.(*net.UDPAddr)
546-
src := netaddr.Unmap(srcu.AddrPort())
545+
src = netaddr.Unmap(src)
547546
if !src.IsValid() {
548547
continue
549548
}
@@ -793,18 +792,14 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
793792
// Nothing more to discover.
794793
return res, nil
795794
}
796-
n, addr, err := uc.ReadFrom(buf)
795+
n, src, err := uc.ReadFromUDPAddrPort(buf)
797796
if err != nil {
798797
if ctx.Err() == context.DeadlineExceeded {
799798
err = nil
800799
}
801800
return res, err
802801
}
803-
ip, ok := netip.AddrFromSlice(addr.(*net.UDPAddr).IP)
804-
if !ok {
805-
continue
806-
}
807-
ip = ip.Unmap()
802+
ip := src.Addr().Unmap()
808803

809804
handleUPnPResponse := func() {
810805
metricUPnPResponse.Add(1)
@@ -832,7 +827,7 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) {
832827
c.mu.Unlock()
833828
}
834829

835-
port := uint16(addr.(*net.UDPAddr).Port)
830+
port := src.Port()
836831
switch port {
837832
case c.upnpPort():
838833
if mem.Contains(mem.B(buf[:n]), mem.S(":InternetGatewayDevice:")) {

net/stun/stuntest/stuntest.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ package stuntest
66

77
import (
88
"context"
9+
"errors"
910
"fmt"
1011
"net"
1112
"net/netip"
1213
"strconv"
13-
"strings"
1414
"sync"
1515
"testing"
1616

17+
"tailscale.com/net/netaddr"
1718
"tailscale.com/net/stun"
1819
"tailscale.com/tailcfg"
1920
"tailscale.com/types/nettype"
@@ -44,28 +45,27 @@ func ServeWithPacketListener(t testing.TB, ln nettype.PacketListener) (addr *net
4445
addr.IP = net.ParseIP("127.0.0.1")
4546
}
4647
doneCh := make(chan struct{})
47-
go runSTUN(t, pc, &stats, doneCh)
48+
go runSTUN(t, pc.(nettype.PacketConn), &stats, doneCh)
4849
return addr, func() {
4950
pc.Close()
5051
<-doneCh
5152
}
5253
}
5354

54-
func runSTUN(t testing.TB, pc net.PacketConn, stats *stunStats, done chan<- struct{}) {
55+
func runSTUN(t testing.TB, pc nettype.PacketConn, stats *stunStats, done chan<- struct{}) {
5556
defer close(done)
5657

5758
var buf [64 << 10]byte
5859
for {
59-
n, addr, err := pc.ReadFrom(buf[:])
60+
n, src, err := pc.ReadFromUDPAddrPort(buf[:])
6061
if err != nil {
61-
// TODO: when we switch to Go 1.16, replace this with errors.Is(err, net.ErrClosed)
62-
if strings.Contains(err.Error(), "closed network connection") {
62+
if errors.Is(err, net.ErrClosed) {
6363
t.Logf("STUN server shutdown")
6464
return
6565
}
6666
continue
6767
}
68-
ua := addr.(*net.UDPAddr)
68+
src = netaddr.Unmap(src)
6969
pkt := buf[:n]
7070
if !stun.Is(pkt) {
7171
continue
@@ -76,16 +76,15 @@ func runSTUN(t testing.TB, pc net.PacketConn, stats *stunStats, done chan<- stru
7676
}
7777

7878
stats.mu.Lock()
79-
if ua.IP.To4() != nil {
79+
if src.Addr().Is4() {
8080
stats.readIPv4++
8181
} else {
8282
stats.readIPv6++
8383
}
8484
stats.mu.Unlock()
8585

86-
nia, _ := netip.AddrFromSlice(ua.IP)
87-
res := stun.Response(txid, netip.AddrPortFrom(nia, uint16(ua.Port)))
88-
if _, err := pc.WriteTo(res, addr); err != nil {
86+
res := stun.Response(txid, src)
87+
if _, err := pc.WriteToUDPAddrPort(res, src); err != nil {
8988
t.Logf("STUN server write failed: %v", err)
9089
}
9190
}

tstest/natlab/natlab.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,21 @@ func (c *conn) Write(buf []byte) (int, error) {
824824
}
825825

826826
func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
827+
n, ap, err := c.ReadFromUDPAddrPort(p)
828+
if err != nil {
829+
return 0, nil, err
830+
}
831+
return n, net.UDPAddrFromAddrPort(ap), nil
832+
}
833+
834+
func (c *conn) ReadFromUDPAddrPort(p []byte) (n int, addr netip.AddrPort, err error) {
827835
ctx, cancel := context.WithCancel(context.Background())
828836
defer cancel()
829837

830838
ar := &activeRead{cancel: cancel}
831839

832840
if err := c.canRead(); err != nil {
833-
return 0, nil, err
841+
return 0, netip.AddrPort{}, err
834842
}
835843

836844
c.registerActiveRead(ar, true)
@@ -840,14 +848,9 @@ func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
840848
case pkt := <-c.in:
841849
n = copy(p, pkt.Payload)
842850
pkt.Trace("PacketConn.ReadFrom")
843-
ua := &net.UDPAddr{
844-
IP: pkt.Src.Addr().AsSlice(),
845-
Port: int(pkt.Src.Port()),
846-
Zone: pkt.Src.Addr().Zone(),
847-
}
848-
return n, ua, nil
851+
return n, pkt.Src, nil
849852
case <-ctx.Done():
850-
return 0, nil, context.DeadlineExceeded
853+
return 0, netip.AddrPort{}, context.DeadlineExceeded
851854
}
852855
}
853856

types/nettype/nettype.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ func (Std) ListenPacket(ctx context.Context, network, address string) (net.Packe
3030
return conf.ListenPacket(ctx, network, address)
3131
}
3232

33-
// PacketConn is a net.PacketConn that's about halfway (as of 2023-04-15)
34-
// converted to use netip.AddrPort.
33+
// PacketConn is like a net.PacketConn but uses the newer netip.AddrPort
34+
// write/read methods.
3535
type PacketConn interface {
3636
WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error)
37-
ReadFrom(p []byte) (int, net.Addr, error)
37+
ReadFromUDPAddrPort([]byte) (int, netip.AddrPort, error)
3838
io.Closer
3939
LocalAddr() net.Addr
4040
SetDeadline(time.Time) error

wgengine/magicsock/magicsock.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"tailscale.com/net/connstats"
4545
"tailscale.com/net/dnscache"
4646
"tailscale.com/net/interfaces"
47+
"tailscale.com/net/netaddr"
4748
"tailscale.com/net/netcheck"
4849
"tailscale.com/net/neterror"
4950
"tailscale.com/net/netns"
@@ -3420,17 +3421,17 @@ type batchingUDPConn struct {
34203421
sendBatchPool sync.Pool
34213422
}
34223423

3423-
func (c *batchingUDPConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
3424+
func (c *batchingUDPConn) ReadFromUDPAddrPort(p []byte) (n int, addr netip.AddrPort, err error) {
34243425
if c.rxOffload {
34253426
// UDP_GRO is opt-in on Linux via setsockopt(). Once enabled you may
34263427
// receive a "monster datagram" from any read call. The ReadFrom() API
34273428
// does not support passing the GSO size and is unsafe to use in such a
34283429
// case. Other platforms may vary in behavior, but we go with the most
34293430
// conservative approach to prevent this from becoming a footgun in the
34303431
// future.
3431-
return 0, nil, errors.New("rx UDP offload is enabled on this socket, single packet reads are unavailable")
3432+
return 0, netip.AddrPort{}, errors.New("rx UDP offload is enabled on this socket, single packet reads are unavailable")
34323433
}
3433-
return c.pc.ReadFrom(p)
3434+
return c.pc.ReadFromUDPAddrPort(p)
34343435
}
34353436

34363437
func (c *batchingUDPConn) SetDeadline(t time.Time) error {
@@ -3753,9 +3754,9 @@ func (c *RebindingUDPConn) currentConn() nettype.PacketConn {
37533754
return c.pconn
37543755
}
37553756

3756-
func (c *RebindingUDPConn) readFromWithInitPconn(pconn nettype.PacketConn, b []byte) (int, net.Addr, error) {
3757+
func (c *RebindingUDPConn) readFromWithInitPconn(pconn nettype.PacketConn, b []byte) (int, netip.AddrPort, error) {
37573758
for {
3758-
n, addr, err := pconn.ReadFrom(b)
3759+
n, addr, err := pconn.ReadFromUDPAddrPort(b)
37593760
if err != nil && pconn != c.currentConn() {
37603761
pconn = *c.pconnAtomic.Load()
37613762
continue
@@ -3764,9 +3765,9 @@ func (c *RebindingUDPConn) readFromWithInitPconn(pconn nettype.PacketConn, b []b
37643765
}
37653766
}
37663767

3767-
// ReadFrom reads a packet from c into b.
3768+
// ReadFromUDPAddrPort reads a packet from c into b.
37683769
// It returns the number of bytes copied and the source address.
3769-
func (c *RebindingUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
3770+
func (c *RebindingUDPConn) ReadFromUDPAddrPort(b []byte) (int, netip.AddrPort, error) {
37703771
return c.readFromWithInitPconn(*c.pconnAtomic.Load(), b)
37713772
}
37723773

@@ -3803,9 +3804,10 @@ func (c *RebindingUDPConn) ReadBatch(msgs []ipv6.Message, flags int) (int, error
38033804
pconn := *c.pconnAtomic.Load()
38043805
b, ok := pconn.(*batchingUDPConn)
38053806
if !ok {
3806-
var err error
3807-
msgs[0].N, msgs[0].Addr, err = c.readFromWithInitPconn(pconn, msgs[0].Buffers[0])
3807+
n, ap, err := c.readFromWithInitPconn(pconn, msgs[0].Buffers[0])
38083808
if err == nil {
3809+
msgs[0].N = n
3810+
msgs[0].Addr = net.UDPAddrFromAddrPort(netaddr.Unmap(ap))
38093811
return 1, nil
38103812
}
38113813
return 0, err
@@ -3880,13 +3882,13 @@ type blockForeverConn struct {
38803882
closed bool
38813883
}
38823884

3883-
func (c *blockForeverConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
3885+
func (c *blockForeverConn) ReadFromUDPAddrPort(p []byte) (n int, addr netip.AddrPort, err error) {
38843886
c.mu.Lock()
38853887
for !c.closed {
38863888
c.cond.Wait()
38873889
}
38883890
c.mu.Unlock()
3889-
return 0, nil, net.ErrClosed
3891+
return 0, netip.AddrPort{}, net.ErrClosed
38903892
}
38913893

38923894
func (c *blockForeverConn) WriteToUDPAddrPort(p []byte, addr netip.AddrPort) (int, error) {

wgengine/magicsock/magicsock_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,7 @@ func TestBlockForeverConnUnblocks(t *testing.T) {
18011801
done := make(chan error, 1)
18021802
go func() {
18031803
defer close(done)
1804-
_, _, err := c.ReadFrom(make([]byte, 1))
1804+
_, _, err := c.ReadFromUDPAddrPort(make([]byte, 1))
18051805
done <- err
18061806
}()
18071807
time.Sleep(50 * time.Millisecond) // give ReadFrom time to get blocked

0 commit comments

Comments
 (0)