wgengine/magicsock: add side-effect-free function for netcheck UDP sends (#13487)

Updates #13484
Updates tailscale/corp#17879

Signed-off-by: Jordan Whited <jordan@tailscale.com>
This commit is contained in:
Jordan Whited 2024-09-16 19:00:12 -07:00 committed by GitHub
parent 8012bb4216
commit 4084c6186d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -493,13 +493,7 @@ func NewConn(opts Options) (*Conn, error) {
c.netChecker = &netcheck.Client{
Logf: logger.WithPrefix(c.logf, "netcheck: "),
NetMon: c.netMon,
SendPacket: func(b []byte, ap netip.AddrPort) (int, error) {
ok, err := c.sendUDP(ap, b)
if !ok {
return 0, err
}
return len(b), err
},
SendPacket: c.sendUDPNetcheck,
SkipExternalNetwork: inTest(),
PortMapper: c.portMapper,
UseDNSCache: true,
@ -582,7 +576,7 @@ func (c *Conn) updateEndpoints(why string) {
c.muCond.Broadcast()
}()
c.dlogf("[v1] magicsock: starting endpoint update (%s)", why)
if c.noV4Send.Load() && runtime.GOOS != "js" {
if c.noV4Send.Load() && runtime.GOOS != "js" && !c.onlyTCP443.Load() {
c.mu.Lock()
closed := c.closed
c.mu.Unlock()
@ -1175,6 +1169,24 @@ func (c *Conn) maybeRebindOnError(os string, err error) bool {
return false
}
// sendUDPNetcheck sends b via UDP to addr. It is used exclusively by netcheck.
// It returns the number of bytes sent along with any error encountered. It
// returns errors.ErrUnsupported if the client is explicitly configured to only
// send data over TCP port 443 and/or we're running on wasm.
func (c *Conn) sendUDPNetcheck(b []byte, addr netip.AddrPort) (int, error) {
if c.onlyTCP443.Load() || runtime.GOOS == "js" {
return 0, errors.ErrUnsupported
}
switch {
case addr.Addr().Is4():
return c.pconn4.WriteToUDPAddrPort(b, addr)
case addr.Addr().Is6():
return c.pconn6.WriteToUDPAddrPort(b, addr)
default:
panic("bogus sendUDPNetcheck addr type")
}
}
// sendUDP sends UDP packet b to addr.
// See sendAddr's docs on the return value meanings.
func (c *Conn) sendUDPStd(addr netip.AddrPort, b []byte) (sent bool, err error) {