From 8fe503057da26a2e29db6ca27d2ef4573ae62395 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 13 Feb 2022 14:45:50 -0800 Subject: [PATCH] net/netutil: unify two oneConnListeners into a new package I was about to add a third copy, so unify them now instead. Change-Id: I3b93896aa1249b1250a6b1df4829d57717f2311a Signed-off-by: Brad Fitzpatrick --- cmd/tailscaled/depaware.txt | 1 + ipn/ipnlocal/peerapi.go | 21 ++-------------- ipn/ipnserver/server.go | 26 ++----------------- net/netutil/netutil.go | 50 +++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 43 deletions(-) create mode 100644 net/netutil/netutil.go diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 1c8ecc4ed..5ecec59dd 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -203,6 +203,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/netknob from tailscale.com/logpolicy+ tailscale.com/net/netns from tailscale.com/cmd/tailscaled+ 💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver + tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+ tailscale.com/net/packet from tailscale.com/net/tstun+ tailscale.com/net/portmapper from tailscale.com/cmd/tailscaled+ tailscale.com/net/proxymux from tailscale.com/cmd/tailscaled diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 8c2fe946b..b720ce08b 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -38,6 +38,7 @@ import ( "tailscale.com/logtail/backoff" "tailscale.com/net/dns/resolver" "tailscale.com/net/interfaces" + "tailscale.com/net/netutil" "tailscale.com/syncs" "tailscale.com/tailcfg" "tailscale.com/util/clientmetric" @@ -506,27 +507,9 @@ func (pln *peerAPIListener) ServeConn(src netaddr.IPPort, c net.Conn) { if addH2C != nil { addH2C(httpServer) } - go httpServer.Serve(&oneConnListener{Listener: pln.ln, conn: c}) + go httpServer.Serve(netutil.NewOneConnListenerFrom(c, pln.ln)) } -type oneConnListener struct { - net.Listener - conn net.Conn -} - -func (l *oneConnListener) Accept() (c net.Conn, err error) { - c = l.conn - if c == nil { - err = io.EOF - return - } - err = nil - l.conn = nil - return -} - -func (l *oneConnListener) Close() error { return nil } - // peerAPIHandler serves the Peer API for a source specific client. type peerAPIHandler struct { ps *peerAPIServer diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 5e93ddd7b..c6ee17138 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -39,6 +39,7 @@ import ( "tailscale.com/ipn/store/aws" "tailscale.com/logtail/backoff" "tailscale.com/net/netstat" + "tailscale.com/net/netutil" "tailscale.com/net/tsdial" "tailscale.com/paths" "tailscale.com/safesocket" @@ -308,7 +309,7 @@ func (s *Server) serveConn(ctx context.Context, c net.Conn, logf logger.Logf) { ErrorLog: logger.StdLogger(logf), Handler: s.localhostHandler(ci), } - httpServer.Serve(&oneConnListener{&protoSwitchConn{s: s, br: br, Conn: c}}) + httpServer.Serve(netutil.NewOneConnListener(&protoSwitchConn{s: s, br: br, Conn: c})) return } @@ -1061,29 +1062,6 @@ func getEngineUntilItWorksWrapper(getEngine func() (wgengine.Engine, error)) fun } } -type dummyAddr string -type oneConnListener struct { - conn net.Conn -} - -func (l *oneConnListener) Accept() (c net.Conn, err error) { - c = l.conn - if c == nil { - err = io.EOF - return - } - err = nil - l.conn = nil - return -} - -func (l *oneConnListener) Close() error { return nil } - -func (l *oneConnListener) Addr() net.Addr { return dummyAddr("unused-address") } - -func (a dummyAddr) Network() string { return string(a) } -func (a dummyAddr) String() string { return string(a) } - // protoSwitchConn is a net.Conn that's we want to speak HTTP to but // it's already had a few bytes read from it to determine that it's // HTTP. So we Read from its bufio.Reader. On Close, we we tell the diff --git a/net/netutil/netutil.go b/net/netutil/netutil.go new file mode 100644 index 000000000..49a2aec64 --- /dev/null +++ b/net/netutil/netutil.go @@ -0,0 +1,50 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package netutil contains misc shared networking code & types. +package netutil + +import ( + "io" + "net" +) + +// NewOneConnListener returns a net.Listener that returns c on its first +// Accept and EOF thereafter. The Listener's Addr is a dummy address. +func NewOneConnListener(c net.Conn) net.Listener { + return NewOneConnListenerFrom(c, dummyListener{}) +} + +// NewOneConnListenerFrom returns a net.Listener wrapping ln where +// its Accept returns c on the first call and io.EOF thereafter. +func NewOneConnListenerFrom(c net.Conn, ln net.Listener) net.Listener { + return &oneConnListener{c, ln} +} + +type oneConnListener struct { + conn net.Conn + net.Listener +} + +func (l *oneConnListener) Accept() (c net.Conn, err error) { + c = l.conn + if c == nil { + err = io.EOF + return + } + err = nil + l.conn = nil + return +} + +type dummyListener struct{} + +func (dummyListener) Close() error { return nil } +func (dummyListener) Addr() net.Addr { return dummyAddr("unused-address") } +func (dummyListener) Accept() (c net.Conn, err error) { return nil, io.EOF } + +type dummyAddr string + +func (a dummyAddr) Network() string { return string(a) } +func (a dummyAddr) String() string { return string(a) }