ipn/ipnserver: start refactoring ipnserver.Run into smaller pieces

I'll keep ipnserver.Run for compatibility, but it'll be a wrapper
around several smaller pieces. (more testable too)

For now, start untangling some things in preparation.

Plan is to have to have a constructor for the just-exported
ipnserver.Server type that takes a LocalBackend and can
accept (in a new method) on a provided listener.

Change-Id: Ide73aadaac1a82605c97a2af1321d0d8f60b2a8c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/3211/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent e4d2ef2b67
commit c23a378f63

@ -171,7 +171,7 @@ func (s *Server) getConnIdentity(c net.Conn) (ci connIdentity, err error) {
return ci, fmt.Errorf("failed to map connection's pid to a user%s: %w", hint, err) return ci, fmt.Errorf("failed to map connection's pid to a user%s: %w", hint, err)
} }
ci.UserID = uid ci.UserID = uid
u, err := s.lookupUserFromID(uid) u, err := lookupUserFromID(s.logf, uid)
if err != nil { if err != nil {
return ci, fmt.Errorf("failed to look up user from userid: %w", err) return ci, fmt.Errorf("failed to look up user from userid: %w", err)
} }
@ -179,10 +179,10 @@ func (s *Server) getConnIdentity(c net.Conn) (ci connIdentity, err error) {
return ci, nil return ci, nil
} }
func (s *Server) lookupUserFromID(uid string) (*user.User, error) { func lookupUserFromID(logf logger.Logf, uid string) (*user.User, error) {
u, err := user.LookupId(uid) u, err := user.LookupId(uid)
if err != nil && runtime.GOOS == "windows" && errors.Is(err, syscall.Errno(0x534)) { if err != nil && runtime.GOOS == "windows" && errors.Is(err, syscall.Errno(0x534)) {
s.logf("[warning] issue 869: os/user.LookupId failed; ignoring") logf("[warning] issue 869: os/user.LookupId failed; ignoring")
// Work around https://github.com/tailscale/tailscale/issues/869 for // Work around https://github.com/tailscale/tailscale/issues/869 for
// now. We don't strictly need the username. It's just a nice-to-have. // now. We don't strictly need the username. It's just a nice-to-have.
// So make up a *user.User if their machine is broken in this way. // So make up a *user.User if their machine is broken in this way.
@ -617,11 +617,8 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (
return fmt.Errorf("safesocket.Listen: %v", err) return fmt.Errorf("safesocket.Listen: %v", err)
} }
server := &Server{ var serverMu sync.Mutex
backendLogID: logid, var serverOrNil *Server
logf: logf,
resetOnZero: !opts.SurviveDisconnects,
}
// When the context is closed or when we return, whichever is first, close our listener // When the context is closed or when we return, whichever is first, close our listener
// and all open connections. // and all open connections.
@ -630,11 +627,16 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (
case <-ctx.Done(): case <-ctx.Done():
case <-runDone: case <-runDone:
} }
server.stopAll() serverMu.Lock()
if s := serverOrNil; s != nil {
s.stopAll()
}
serverMu.Unlock()
listen.Close() listen.Close()
}() }()
logf("Listening on %v", listen.Addr()) logf("Listening on %v", listen.Addr())
var serverModeUser *user.User
var store ipn.StateStore var store ipn.StateStore
if opts.StatePath != "" { if opts.StatePath != "" {
const kubePrefix = "kube:" const kubePrefix = "kube:"
@ -669,12 +671,12 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (
key := string(autoStartKey) key := string(autoStartKey)
if strings.HasPrefix(key, "user-") { if strings.HasPrefix(key, "user-") {
uid := strings.TrimPrefix(key, "user-") uid := strings.TrimPrefix(key, "user-")
u, err := server.lookupUserFromID(uid) u, err := lookupUserFromID(logf, uid)
if err != nil { if err != nil {
logf("ipnserver: found server mode auto-start key %q; failed to load user: %v", key, err) logf("ipnserver: found server mode auto-start key %q; failed to load user: %v", key, err)
} else { } else {
logf("ipnserver: found server mode auto-start key %q (user %s)", key, u.Username) logf("ipnserver: found server mode auto-start key %q (user %s)", key, u.Username)
server.serverModeUser = u serverModeUser = u
} }
opts.AutostartStateKey = ipn.StateKey(key) opts.AutostartStateKey = ipn.StateKey(key)
} }
@ -732,9 +734,19 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() (
}) })
} }
server.b = b server := &Server{
b: b,
backendLogID: logid,
logf: logf,
resetOnZero: !opts.SurviveDisconnects,
serverModeUser: serverModeUser,
}
server.bs = ipn.NewBackendServer(logf, b, server.writeToClients) server.bs = ipn.NewBackendServer(logf, b, server.writeToClients)
serverMu.Lock()
serverOrNil = server
serverMu.Unlock()
if opts.AutostartStateKey != "" { if opts.AutostartStateKey != "" {
server.bs.GotCommand(context.TODO(), &ipn.Command{ server.bs.GotCommand(context.TODO(), &ipn.Command{
Version: version.Long, Version: version.Long,

Loading…
Cancel
Save