derp: introduce Conn interface

This lets us test with something other than a net.Conn.

Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
This commit is contained in:
David Crawshaw
2020-03-12 11:05:03 -04:00
committed by David Crawshaw
parent 41ac4a79d6
commit 43aa8595dd
4 changed files with 31 additions and 18 deletions

View File

@@ -18,7 +18,6 @@ import (
"io"
"io/ioutil"
"math/big"
"net"
"os"
"strconv"
"sync"
@@ -57,11 +56,23 @@ type Server struct {
mu sync.Mutex
closed bool
netConns map[net.Conn]chan struct{} // chan is closed when conn closes
netConns map[Conn]chan struct{} // chan is closed when conn closes
clients map[key.Public]*sclient
clientsEver map[key.Public]bool // never deleted from, for stats; fine for now
}
// Conn is the subset of the underlying net.Conn the DERP Server needs.
// It is a defined type so that non-net connections can be used.
type Conn interface {
io.Closer
// The *Deadline methods follow the semantics of net.Conn.
SetDeadline(time.Time) error
SetReadDeadline(time.Time) error
SetWriteDeadline(time.Time) error
}
// NewServer returns a new DERP server. It doesn't listen on its own.
// Connections are given to it via Server.Accept.
func NewServer(privateKey key.Private, logf logger.Logf) *Server {
@@ -71,7 +82,7 @@ func NewServer(privateKey key.Private, logf logger.Logf) *Server {
logf: logf,
clients: make(map[key.Public]*sclient),
clientsEver: make(map[key.Public]bool),
netConns: make(map[net.Conn]chan struct{}),
netConns: make(map[Conn]chan struct{}),
}
return s
}
@@ -115,7 +126,7 @@ func (s *Server) isClosed() bool {
// on its own.
//
// Accept closes nc.
func (s *Server) Accept(nc net.Conn, brw *bufio.ReadWriter) {
func (s *Server) Accept(nc Conn, brw *bufio.ReadWriter, remoteAddr string) {
closed := make(chan struct{})
s.accepts.Add(1)
@@ -132,8 +143,8 @@ func (s *Server) Accept(nc net.Conn, brw *bufio.ReadWriter) {
s.mu.Unlock()
}()
if err := s.accept(nc, brw); err != nil && !s.isClosed() {
s.logf("derp: %s: %v", nc.RemoteAddr(), err)
if err := s.accept(nc, brw, remoteAddr); err != nil && !s.isClosed() {
s.logf("derp: %s: %v", remoteAddr, err)
}
}
@@ -147,8 +158,8 @@ func (s *Server) registerClient(c *sclient) {
c.logf("adding connection")
} else {
s.clientsReplaced.Add(1)
old.nc.Close()
c.logf("adding connection, replacing %s", old.nc.RemoteAddr())
c.logf("adding connection, replacing %s", old.remoteAddr)
go old.nc.Close()
}
s.clients[c.key] = c
s.clientsEver[c.key] = true
@@ -171,7 +182,7 @@ func (s *Server) unregisterClient(c *sclient) {
}
}
func (s *Server) accept(nc net.Conn, brw *bufio.ReadWriter) error {
func (s *Server) accept(nc Conn, brw *bufio.ReadWriter, remoteAddr string) error {
br, bw := brw.Reader, brw.Writer
nc.SetDeadline(time.Now().Add(10 * time.Second))
if err := s.sendServerKey(bw); err != nil {
@@ -203,7 +214,8 @@ func (s *Server) accept(nc net.Conn, brw *bufio.ReadWriter) error {
br: br,
bw: bw,
limiter: limiter,
logf: logger.WithPrefix(s.logf, fmt.Sprintf("derp client %v/%x: ", nc.RemoteAddr(), clientKey)),
logf: logger.WithPrefix(s.logf, fmt.Sprintf("derp client %v/%x: ", remoteAddr, clientKey)),
remoteAddr: remoteAddr,
connectedAt: time.Now(),
}
if clientInfo != nil {
@@ -450,11 +462,12 @@ func (s *Server) recvPacket(ctx context.Context, br *bufio.Reader, frameLen uint
// (The "s" prefix is to more explicitly distinguish it from Client in derp_client.go)
type sclient struct {
s *Server
nc net.Conn
nc Conn
key key.Public
info clientInfo
logf logger.Logf
limiter *rate.Limiter
remoteAddr string // usually ip:port from net.Conn.RemoteAddr().String()
connectedAt time.Time
keepAliveTimer *time.Timer