tailscale/ipn/desktop/sessions.go
Nick Khyl bc0cd512ee ipn/desktop: add a new package for managing desktop sessions on Windows
This PR adds a new package, ipn/desktop, which provides a platform-agnostic
interface for enumerating desktop sessions and registering session callbacks.
Currently, it is implemented only for Windows.

Updates #14823

Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-02-11 15:31:42 -06:00

61 lines
2.8 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package desktop
import (
"errors"
"runtime"
)
// ErrNotImplemented is returned by [NewSessionManager] when it is not
// implemented for the current GOOS.
var ErrNotImplemented = errors.New("not implemented for GOOS=" + runtime.GOOS)
// SessionInitCallback is a function that is called once per [Session].
// It returns an optional cleanup function that is called when the session
// is about to be destroyed, or nil if no cleanup is needed.
// It is not safe to call SessionManager methods from within the callback.
type SessionInitCallback func(session *Session) (cleanup func())
// SessionStateCallback is a function that reports the initial or updated
// state of a [Session], such as when it transitions between foreground and background.
// It is guaranteed to be called after all registered [SessionInitCallback] functions
// have completed, and before any cleanup functions are called for the same session.
// It is not safe to call SessionManager methods from within the callback.
type SessionStateCallback func(session *Session)
// SessionManager is an interface that provides access to desktop sessions on the current platform.
// It is safe for concurrent use.
type SessionManager interface {
// Init explicitly initializes the receiver.
// Unless the receiver is explicitly initialized, it will be lazily initialized
// on the first call to any other method.
// It is safe to call Init multiple times.
Init() error
// Sessions returns a session snapshot taken at the time of the call.
// Since sessions can be created or destroyed at any time, it may become
// outdated as soon as it is returned.
//
// It is primarily intended for logging and debugging.
// Prefer registering a [SessionInitCallback] or [SessionStateCallback]
// in contexts requiring stronger guarantees.
Sessions() (map[SessionID]*Session, error)
// RegisterInitCallback registers a [SessionInitCallback] that is called for each existing session
// and for each new session that is created, until the returned unregister function is called.
// If the specified [SessionInitCallback] returns a cleanup function, it is called when the session
// is about to be destroyed. The callback function is guaranteed to be called once and only once
// for each existing and new session.
RegisterInitCallback(cb SessionInitCallback) (unregister func(), err error)
// RegisterStateCallback registers a [SessionStateCallback] that is called for each existing session
// and every time the state of a session changes, until the returned unregister function is called.
RegisterStateCallback(cb SessionStateCallback) (unregister func(), err error)
// Close waits for all registered callbacks to complete
// and releases resources associated with the receiver.
Close() error
}