@ -17,11 +17,11 @@ import (
"tailscale.com/net/netutil"
"tailscale.com/net/netutil"
)
)
// web Server holds state for the web interface for managing
// web Client holds state for the web interface for managing
// this tailscale instance. The web interface is not used by
// this tailscale instance. The web interface is not used by
// default, but initialized by calling LocalBackend.WebOrInit.
// default, but initialized by calling LocalBackend.WebOrInit.
type web Server struct {
type web Client struct {
w s * web . Server // or nil, initialized lazily
server * web . Server // or nil, initialized lazily
// lc optionally specifies a LocalClient to use to connect
// lc optionally specifies a LocalClient to use to connect
// to the localapi for this tailscaled instance.
// to the localapi for this tailscaled instance.
@ -34,57 +34,56 @@ type webServer struct {
func ( b * LocalBackend ) SetWebLocalClient ( lc * tailscale . LocalClient ) {
func ( b * LocalBackend ) SetWebLocalClient ( lc * tailscale . LocalClient ) {
b . mu . Lock ( )
b . mu . Lock ( )
defer b . mu . Unlock ( )
defer b . mu . Unlock ( )
b . web . lc = lc
b . web Client . lc = lc
}
}
// Web Init initializes the web interface for managing
// Web Client Init initializes the web interface for managing this
// t his t ailscaled instance. If the web interface is
// t ailscaled instance.
// already running, WebInit is a no-op.
// If the web interface is already running, WebClient Init is a no-op.
func ( b * LocalBackend ) Web Init( ) ( err error ) {
func ( b * LocalBackend ) Web Client Init( ) ( err error ) {
if ! envknob . Bool ( "TS_DEBUG_WEB_UI" ) {
if ! envknob . Bool ( "TS_DEBUG_WEB_UI" ) {
return errors . New ( "web ui flag unset" )
return errors . New ( "web ui flag unset" )
}
}
b . mu . Lock ( )
b . mu . Lock ( )
defer b . mu . Unlock ( )
defer b . mu . Unlock ( )
if b . web . w s != nil {
if b . web Client . server != nil {
return nil
return nil
}
}
b . logf ( "Web Init: initializing web ui")
b . logf ( "Web Client Init: initializing web ui")
if b . web . w s, err = web . NewServer ( web . ServerOpts {
if b . web Client . server , err = web . NewServer ( web . ServerOpts {
// TODO(sonia): allow passing back dev mode flag
// TODO(sonia): allow passing back dev mode flag
LocalClient : b . web . lc ,
LocalClient : b . web Client . lc ,
Logf : b . logf ,
Logf : b . logf ,
} ) ; err != nil {
} ) ; err != nil {
return fmt . Errorf ( "web.NewServer: %w" , err )
return fmt . Errorf ( "web.NewServer: %w" , err )
}
}
b . logf ( "Web Init: started web ui")
b . logf ( "Web Client Init: started web ui")
return nil
return nil
}
}
// WebShutdown shuts down any running b.web servers and
// WebClientShutdown shuts down any running b.webClient servers and
// clears out b.web state (besides the b.web.lc field,
// clears out b.webClient state (besides the b.webClient.lc field,
// which is left untouched because required for future
// which is left untouched because required for future web startups).
// web startups).
// WebClientShutdown obtains the b.mu lock.
// WebShutdown obtains the b.mu lock.
func ( b * LocalBackend ) WebClientShutdown ( ) {
func ( b * LocalBackend ) WebShutdown ( ) {
b . mu . Lock ( )
b . mu . Lock ( )
webS := b . web . ws
server := b . webClient . server
b . web . w s = nil
b . web Client . server = nil
b . mu . Unlock ( ) // release lock before shutdown
b . mu . Unlock ( ) // release lock before shutdown
if webS != nil {
if server != nil {
b. web . w s. Shutdown ( )
server . Shutdown ( )
}
}
b . logf ( "Web Shutdown: shut down web ui")
b . logf ( "Web Client Shutdown: shut down web ui")
}
}
// handleWebClientConn serves web client requests.
// handleWebClientConn serves web client requests.
func ( b * LocalBackend ) handleWebClientConn ( c net . Conn ) error {
func ( b * LocalBackend ) handleWebClientConn ( c net . Conn ) error {
if err := b . Web Init( ) ; err != nil {
if err := b . Web Client Init( ) ; err != nil {
return err
return err
}
}
s := http . Server { Handler : b . web . w s}
s := http . Server { Handler : b . web Client . server }
return s . Serve ( netutil . NewOneConnListener ( c , nil ) )
return s . Serve ( netutil . NewOneConnListener ( c , nil ) )
}
}