derp: change NewClient constructor to an option pattern

(The NewMeshClient constructor I added recently was gross in
retrospect at call sites, especially when it wasn't obvious that a
meshKey empty string meant a regular client)
reviewable/pr440/r1
Brad Fitzpatrick 5 years ago
parent 4d599d194f
commit 5e0ff494a5

@ -34,16 +34,38 @@ type Client struct {
readErr error // sticky read error readErr error // sticky read error
} }
func NewClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf) (*Client, error) { // ClientOpt is an option passed to NewClient.
noMeshKey := "" type ClientOpt interface {
return NewMeshClient(privateKey, nc, brw, logf, noMeshKey) update(*clientOpt)
} }
// NewMeshClient is the Client constructor for trusted clients that type clientOptFunc func(*clientOpt)
// are a peer in a cluster mesh.
func (f clientOptFunc) update(o *clientOpt) { f(o) }
// clientOpt are the options passed to newClient.
type clientOpt struct {
MeshKey string
}
// MeshKey returns a ClientOpt to pass to the DERP server during connect to get
// access to join the mesh.
// //
// An empty meshKey is equivalent to just using NewClient. // An empty key means to not use a mesh key.
func NewMeshClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, meshKey string) (*Client, error) { func MeshKey(key string) ClientOpt { return clientOptFunc(func(o *clientOpt) { o.MeshKey = key }) }
func NewClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opts ...ClientOpt) (*Client, error) {
var opt clientOpt
for _, o := range opts {
if o == nil {
return nil, errors.New("nil ClientOpt")
}
o.update(&opt)
}
return newClient(privateKey, nc, brw, logf, opt)
}
func newClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf logger.Logf, opt clientOpt) (*Client, error) {
c := &Client{ c := &Client{
privateKey: privateKey, privateKey: privateKey,
publicKey: privateKey.Public(), publicKey: privateKey.Public(),
@ -51,7 +73,7 @@ func NewMeshClient(privateKey key.Private, nc Conn, brw *bufio.ReadWriter, logf
nc: nc, nc: nc,
br: brw.Reader, br: brw.Reader,
bw: brw.Writer, bw: brw.Writer,
meshKey: meshKey, meshKey: opt.MeshKey,
} }
if err := c.recvServerKey(); err != nil { if err := c.recvServerKey(); err != nil {
return nil, fmt.Errorf("derp.Client: failed to receive server key: %v", err) return nil, fmt.Errorf("derp.Client: failed to receive server key: %v", err)

@ -510,7 +510,7 @@ func newRegularClient(t *testing.T, ts *testServer, name string) *testClient {
func newTestWatcher(t *testing.T, ts *testServer, name string) *testClient { func newTestWatcher(t *testing.T, ts *testServer, name string) *testClient {
return newTestClient(t, ts, name, func(nc net.Conn, priv key.Private, logf logger.Logf) (*Client, error) { return newTestClient(t, ts, name, func(nc net.Conn, priv key.Private, logf logger.Logf) (*Client, error) {
brw := bufio.NewReadWriter(bufio.NewReader(nc), bufio.NewWriter(nc)) brw := bufio.NewReadWriter(bufio.NewReader(nc), bufio.NewWriter(nc))
c, err := NewMeshClient(priv, nc, brw, logf, "mesh-key") c, err := NewClient(priv, nc, brw, logf, MeshKey("mesh-key"))
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -282,7 +282,7 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
return nil, 0, fmt.Errorf("GET failed: %v: %s", err, b) return nil, 0, fmt.Errorf("GET failed: %v: %s", err, b)
} }
derpClient, err := derp.NewMeshClient(c.privateKey, httpConn, brw, c.logf, c.MeshKey) derpClient, err := derp.NewClient(c.privateKey, httpConn, brw, c.logf, derp.MeshKey(c.MeshKey))
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }

Loading…
Cancel
Save