Files
.bencher
.github
appc
atomicfile
chirp
client
clientupdate
cmd
control
derp
disco
docs
doctor
drive
envknob
feature
gokrazy
health
hostinfo
internal
ipn
jsondb
k8s-operator
kube
licenses
log
logpolicy
logtail
maths
metrics
net
art
bakedroots
captivedetection
connstats
dns
dnscache
dnsfallback
flowtrack
ipset
ktimeout
memnet
netaddr
netcheck
neterror
netkernelconf
netknob
netmon
netns
netstat
netutil
netx
netx.go
packet
ping
portmapper
proxymux
routetable
socks5
sockstats
speedtest
stun
stunserver
tcpinfo
tlsdial
tsaddr
tsdial
tshttpproxy
tstun
udprelay
wsconn
omit
packages
paths
portlist
posture
prober
proxymap
release
safesocket
safeweb
scripts
sessionrecording
smallzstd
ssh
syncs
tailcfg
tempfork
tka
tool
tsconsensus
tsconst
tsd
tsnet
tstest
tstime
tsweb
types
util
version
wf
wgengine
words
.gitattributes
.gitignore
.golangci.yml
ALPINE.txt
AUTHORS
CODEOWNERS
CODE_OF_CONDUCT.md
Dockerfile
Dockerfile.base
LICENSE
Makefile
PATENTS
README.md
SECURITY.md
VERSION.txt
api.md
assert_ts_toolchain_match.go
build_dist.sh
build_docker.sh
flake.lock
flake.nix
go.mod
go.mod.sri
go.sum
go.toolchain.branch
go.toolchain.rev
gomod_test.go
header.txt
pkgdoc_test.go
pull-toolchain.sh
shell.nix
staticcheck.conf
update-flake.sh
version-embed.go
version_tailscale_test.go
version_test.go
tailscale/net/netx/netx.go
Brad Fitzpatrick fb96137d79 net/{netx,memnet},all: add netx.DialFunc, move memnet Network impl
This adds netx.DialFunc, unifying a type we have a bazillion other
places, giving it now a nice short name that's clickable in
editors, etc.

That highlighted that my earlier move (03b47a55c7) of stuff from
nettest into netx moved too much: it also dragged along the memnet
impl, meaning all users of netx.DialFunc who just wanted netx for the
type definition were instead also pulling in all of memnet.

So move the memnet implementation netx.Network into memnet, a package
we already had.

Then use netx.DialFunc in a bunch of places. I'm sure I missed some.
And plenty remain in other repos, to be updated later.

Updates 

Change-Id: I7296cd4591218e8624e214f8c70dab05fb884e95
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-04-08 10:07:47 -07:00

54 lines
1.7 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package netx contains types to describe and abstract over how dialing and
// listening are performed.
package netx
import (
"context"
"fmt"
"net"
)
// DialFunc is a function that dials a network address.
//
// It's the type implemented by net.Dialer.DialContext or required
// by net/http.Transport.DialContext, etc.
type DialFunc func(ctx context.Context, network, address string) (net.Conn, error)
// Network describes a network that can listen and dial. The two common
// implementations are [RealNetwork], using the net package to use the real
// network, or [memnet.Network], using an in-memory network (typically for testing)
type Network interface {
NewLocalTCPListener() net.Listener
Listen(network, address string) (net.Listener, error)
Dial(ctx context.Context, network, address string) (net.Conn, error)
}
// RealNetwork returns a Network implementation that uses the real
// net package.
func RealNetwork() Network { return realNetwork{} }
// realNetwork implements [Network] using the real net package.
type realNetwork struct{}
func (realNetwork) Listen(network, address string) (net.Listener, error) {
return net.Listen(network, address)
}
func (realNetwork) Dial(ctx context.Context, network, address string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, network, address)
}
func (realNetwork) NewLocalTCPListener() net.Listener {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
if ln, err = net.Listen("tcp6", "[::1]:0"); err != nil {
panic(fmt.Sprintf("failed to listen on either IPv4 or IPv6 localhost port: %v", err))
}
}
return ln
}