diff --git a/.forgejo/workflows/build-dev.yml b/.forgejo/workflows/build-dev.yml index 2e10494..0a17c67 100644 --- a/.forgejo/workflows/build-dev.yml +++ b/.forgejo/workflows/build-dev.yml @@ -6,7 +6,7 @@ # binaries instead of building everything from source, resulting in faster # updates, once updates work again that is... on: - push: + pull_request: branches: - dev diff --git a/changelog.md b/changelog.md deleted file mode 100644 index 8124dd0..0000000 --- a/changelog.md +++ /dev/null @@ -1,28 +0,0 @@ -# Changelog - -## [Unreleased] - -### Added - -- Added proclamation sync when entering "proclamations" settings page - -### Changed - -- Changed audio devices page to be strictly an audio on/off toggle -- Changed settings menu items to be left-aligned with eachother -- Changed settings entry organization - -### Deprecated - -### Removed - -- Removed list of audio devices from audio device page - -### Fixed - -- Fixed audio device not being initialized on first entry to F2 screen - -### Security - ---- - diff --git a/go.mod b/go.mod index cbd77b7..225109e 100644 --- a/go.mod +++ b/go.mod @@ -8,11 +8,11 @@ require github.com/veandco/go-sdl2 v0.4.40 require github.com/go-gl/mathgl v1.2.0 -require ( - github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 - github.com/godbus/dbus/v5 v5.1.0 - github.com/google/uuid v1.6.0 -) +require github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 + +require github.com/Wifx/gonetworkmanager/v2 v2.2.0 + +require github.com/godbus/dbus/v5 v5.1.0 // indirect require ( github.com/jinzhu/inflection v1.0.0 // indirect diff --git a/go.sum b/go.sum index 8b36dab..070ce89 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,12 @@ +github.com/Wifx/gonetworkmanager/v2 v2.2.0 h1:kPstgsQtY8CmDOOFZd81ytM9Gi3f6ImzPCKF7nNhQ2U= +github.com/Wifx/gonetworkmanager/v2 v2.2.0/go.mod h1:fMDb//SHsKWxyDUAwXvCqurV3npbIyyaQWenGpZ/uXg= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= github.com/go-gl/mathgl v1.2.0 h1:v2eOj/y1B2afDxF6URV1qCYmo1KW08lAMtTbOn3KXCY= github.com/go-gl/mathgl v1.2.0/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= diff --git a/internal/application/application.go b/internal/application/application.go index f985138..7719c37 100644 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -4,7 +4,6 @@ import ( "errors" "os" "path/filepath" - "sync/atomic" "time" "github.com/go-gl/gl/v3.3-core/gl" @@ -51,7 +50,6 @@ type Application struct { pendingAction func() running bool DB *gorm.DB - Config atomic.Pointer[db.AppConfig] PageRouter *page.Router state State } @@ -68,8 +66,6 @@ func Run() { var homeDir string var dataDir string var DB *gorm.DB - var initialConfig db.AppConfig - var result *gorm.DB networkIsUp = false @@ -110,14 +106,15 @@ func Run() { return } - // Populate the initial Config cache OR create defaults firstRun := false - result = DB.First(&initialConfig) - if result.Error != nil { - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - logger.Info("First run detected: Creating default configuration...") + + // Populate the initial Config cache OR create defaults + cfg, err := db.GetConfig(DB) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { firstRun = true - initialConfig = db.AppConfig{ + cfg = &db.AppConfig{ + Model: gorm.Model{ID: 1}, DataDir: dataDir, AssetsDir: dataDir, SystemLevel: "BASIC", @@ -128,13 +125,11 @@ func Run() { AudioEnabled: true, SavedVolume: 1.0, } - if err := DB.Create(&initialConfig).Error; err != nil { - logger.Error("failed to insert default config into database: %v", err) + + if err := DB.Create(cfg).Error; err != nil { + logger.Error("failed to create config: %v", err) return } - } else { - logger.Error("error querying database for initial config: %v", result.Error) - return } } @@ -148,8 +143,6 @@ func Run() { app.state = FIRST_RUN } - app.refreshCache() - w, h := app.initializeSDLAndOpenGL() defer app.cleanup() @@ -159,12 +152,10 @@ func Run() { downloadProgressChan := make(chan download.DownloadStatus, 1000) app.PageRouter = page.NewRouter(page.PageCtx{ - CfgPtr: app.Config.Load(), DbPtr: app.DB, W: w, H: h, MessageChannel: downloadProgressChan, - RefreshConfig: app.refreshCache, }) // Sync the proclamations from the API to the Database @@ -188,7 +179,12 @@ func Run() { "PinealGland.wav", } - go download.DownloadAudioFiles(app.PageRouter.Context.MessageChannel, audioFileNames, filepath.Join(app.PageRouter.Context.CfgPtr.AssetsDir, "audio")) + config, err := db.GetConfig(app.DB) + if err != nil { + panic(err) + } + + go download.DownloadAudioFiles(app.PageRouter.Context.MessageChannel, audioFileNames, filepath.Join(config.AssetsDir, "audio")) app.runEventLoop() } @@ -204,25 +200,16 @@ func (app *Application) checkState() { // Check if there is an internet connection, and if not, force the WiFi page if !networkIsUp { if lastNetworkCheckTime.IsZero() || time.Since(lastNetworkCheckTime) >= time.Second { - networkManager, err := network.New() - if err != nil { - logger.Error("error obtaining a network manager %v", err) - return - } lastNetworkCheckTime = time.Now() - status, err := networkManager.CheckInternetConnection() - if err != nil { - logger.Error("error checking for internet connection %v", err) - return - } - if status.StatusCode != network.StatusWifiConnectedInternetUp && - status.StatusCode != network.StatusEthernetConnectedInternetUp { + + if !network.HasInternet() { if app.state != NEEDS_INTERNET { app.PageRouter.NavigateTo(page.WIFI) app.state = NEEDS_INTERNET } return } + networkIsUp = true // internet confirmed, don't check again } else { return // throttled, and we don't yet know if network is up — can't proceed @@ -230,7 +217,12 @@ func (app *Application) checkState() { } // Then check for an email address - if app.Config.Load().EmailAddress == "" { + config, err := db.GetConfig(app.DB) + if err != nil { + panic(err) + } + + if config.EmailAddress == "" { if app.state != NEEDS_EMAIL_ADDRESS { app.PageRouter.NavigateTo(page.EMAIL_ADDRESS) app.state = NEEDS_EMAIL_ADDRESS @@ -239,7 +231,11 @@ func (app *Application) checkState() { } // Then check for a license key - if app.Config.Load().LicenseKey == "" { + config, err = db.GetConfig(app.DB) + if err != nil { + panic(err) + } + if config.LicenseKey == "" { if app.state != NEEDS_LICENSE_KEY { app.PageRouter.NavigateTo(page.LICENSE_KEY) app.state = NEEDS_LICENSE_KEY @@ -251,14 +247,6 @@ func (app *Application) checkState() { app.PageRouter.NavigateTo(page.HOME) } -func (app *Application) refreshCache() { - var freshConfig db.AppConfig - if result := app.DB.First(&freshConfig); result.Error != nil { - logger.Error("failed to fetch configuration from the database: %v", result.Error) - } - app.Config.Store(&freshConfig) -} - func (app *Application) initializeSDLAndOpenGL() (W, H int32) { logger.Info("Initializing SDL") if err := sdl.Init(sdl.INIT_VIDEO | sdl.INIT_AUDIO); err != nil { @@ -333,29 +321,38 @@ func (app *Application) initializeSDLAndOpenGL() (W, H int32) { func (app *Application) initializeManagers() { logger.Info("Initializing ShaderManager") - shaderDir := filepath.Join(app.Config.Load().AssetsDir, "shaders") + config, err := db.GetConfig(app.DB) + if err != nil { + panic(err) + } + shaderDir := filepath.Join(config.AssetsDir, "shaders") logger.Info("Loading shaders from %s", shaderDir) if err := shaderManager.InitShaderManager(shaderDir); err != nil { logger.Fatal("ShaderManager initialization failed: %v", err) } logger.Info("Initializing FontManager") - if err := fontManager.InitFontManager(app.Config.Load()); err != nil { + if err := fontManager.InitFontManager(config); err != nil { logger.Fatal("FontManager initialization failed: %v", err) } } func (app *Application) initializeAudio() { logger.Info("Initializing audio") - - if err := mixer.Init(app.Config.Load(), app.refreshCache); err != nil { - logger.Error("Unable to initialize audio device '%s': %v", app.Config.Load().SelectedAudioDevice, err) + config, err := db.GetConfig(app.DB) + if err != nil { + panic(err) + } + if err := mixer.Init(config, app.refreshCache); err != nil { + logger.Error("Unable to initialize audio device '%s': %v", config.SelectedAudioDevice, err) logger.Error("Audio will be unavailable until a device is configured") } else { - logger.Info("Audio initialized with device: '%s'", app.Config.Load().SelectedAudioDevice) + logger.Info("Audio initialized with device: '%s'", config.SelectedAudioDevice) } } +func (app *Application) refreshCache() {} + func (app *Application) cleanup() { logger.Info("Cleaning up") diff --git a/internal/db/DB.go b/internal/db/DB.go index e290f79..658820a 100644 --- a/internal/db/DB.go +++ b/internal/db/DB.go @@ -80,6 +80,7 @@ func Connect(dbpath string) (*gorm.DB, error) { return nil, fmt.Errorf("could not get underlying sql.DB: %w", err) } sqlDB.SetMaxOpenConns(1) + sqlDB.SetMaxIdleConns(1) // ── Pragmas ─────────────────────────────────────────────────────────── pragmas := []string{ diff --git a/internal/db/queries.go b/internal/db/queries.go new file mode 100644 index 0000000..de2ed52 --- /dev/null +++ b/internal/db/queries.go @@ -0,0 +1,14 @@ +package db + +import "gorm.io/gorm" + +// GetConfig fetches the application config from the database +func GetConfig(db *gorm.DB) (*AppConfig, error) { + var cfg AppConfig + err := db.First(&cfg, 1).Error + if err != nil { + return nil, err + } + + return &cfg, nil +} diff --git a/internal/download/Download.go b/internal/download/Download.go index 2d3c467..b035285 100644 --- a/internal/download/Download.go +++ b/internal/download/Download.go @@ -192,8 +192,6 @@ func DownloadAudioFiles(progressChan chan<- DownloadStatus, filenames []string, return } - logger.Info("Finished downloading %s", filename) - // Update progress totalDownloaded += int64(n) progressChan <- DownloadStatus{ diff --git a/internal/fontManager/fontManager.go b/internal/fontManager/fontManager.go index 99358a5..20e0096 100644 --- a/internal/fontManager/fontManager.go +++ b/internal/fontManager/fontManager.go @@ -57,7 +57,7 @@ func InitFontManager(cfg *db.AppConfig) error { // --- NEW: Create the scrambled font after loading normal fonts --- // We will use "DejaVuSans" as the base. If you use a different default font, // change this string. - baseFontForScramble := "Roboto-Regular" + baseFontForScramble := "SpaceMonoNerdFont-Regular" if _, ok := fm.Fonts[baseFontForScramble]; ok { if err := fm.CreateScrambledFont(baseFontForScramble, "Scrambled"); err != nil { // This is not a fatal error for the whole application, so we just log it. @@ -506,26 +506,27 @@ func (fm *FontManager) createFontMap(font *FontEntry, scramble bool, baseFont *F 126, // ~ // Common Unicode punctuation - 161, // ¡ - 191, // ¿ - 8211, // – - 8212, // — - 8216, // ‘ - 8217, // ’ - 8220, // “ - 8221, // ” - 8226, // • - 8230, // … - 8240, // ‰ - 8364, // € - 162, // ¢ - 163, // £ - 165, // ¥ - 169, // © - 174, // ® - 8482, // ™ - 232, // è - 233, // é + 161, // ¡ + 191, // ¿ + 8211, // – + 8212, // — + 8216, // ‘ + 8217, // ’ + 8220, // “ + 8221, // ” + 8226, // • + 8230, // … + 8240, // ‰ + 8364, // € + 162, // ¢ + 163, // £ + 165, // ¥ + 169, // © + 174, // ® + 8482, // ™ + 232, // è + 233, // é + 10003, // checkmark } tempGlyphs := make([]TempGlyph, 0, len(chars)) var totalWidth, maxHeight int32 diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 4609f90..8214b06 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -10,6 +10,8 @@ import ( "rhemawavetech.com/rhemawave/internal/db" ) +// ─── Level ─────────────────────────────────────────────────────────────────── + type Level int const ( @@ -24,82 +26,206 @@ func (l Level) String() string { return [...]string{"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"}[l] } +// ─── Internal entry type ────────────────────────────────────────────────────── + +type entry struct { + level Level + message string + timestamp time.Time + fatal bool +} + +// ─── Package state ──────────────────────────────────────────────────────────── + var ( - DB *gorm.DB - file *os.File - console = log.New(os.Stderr, "", 0) SetLevel Level = LevelInfo + console = log.New(os.Stderr, "", 0) + + ch chan entry // unbuffered send is a bug; always buffered + done chan struct{} + db_ *gorm.DB + file *os.File ) -// AddFile attaches or replaces the file backend +func init() { + ch = make(chan entry, 4096) + done = make(chan struct{}) + go drain() +} + +// ─── Configuration ──────────────────────────────────────────────────────────── + +// AddFile attaches or replaces the file backend. Safe to call at any time. func AddFile(path string) error { + f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + return fmt.Errorf("logger: open file: %w", err) + } + // Send a sentinel that carries the new file handle. + // We do this through the channel so the drain goroutine owns + // all file state — no mutex needed. + fileSwapCh <- f + return nil +} + +// AddDatabase attaches or replaces the database backend. Safe to call at any time. +func AddDatabase(d *gorm.DB) { + dbSwapCh <- d +} + +// Close drains remaining entries and shuts down the logger. +// Call this with defer in main(). +func Close() { + close(done) + <-drainDone // wait for drain goroutine to finish flushing if file != nil { file.Close() - } - - _, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) - if err != nil { - return err - } - - return nil -} - -// AddDatabase attaches or replaces the database backend -func AddDatabase(d *gorm.DB) { - console.Println("Adding database to logger") - DB = d -} - -// Close shuts down the file backend. -func Close() error { - if file != nil { - err := file.Close() file = nil - return err } - return nil } -func logMsg(level Level, format string, args ...any) { - if level == LevelDebug && SetLevel != LevelDebug { - return - } - message := fmt.Sprintf(format, args...) - now := time.Now() - timestamp := now.Format("2006-01-02 15:04:05.000") - line := fmt.Sprintf("%s [%s] %s", timestamp, level, message) +// ─── Swap channels (owned exclusively by drain goroutine) ──────────────────── - // 1. The standard log package is internally thread-safe - console.Println(line) +var ( + fileSwapCh = make(chan *os.File, 1) + dbSwapCh = make(chan *gorm.DB, 1) + drainDone = make(chan struct{}) +) - // 2. Write to file - if file != nil { - fmt.Fprintln(file, line) +// ─── Drain goroutine ────────────────────────────────────────────────────────── +// +// This is the ONLY goroutine that touches file, db_, or does DB writes. +// Everything else just sends to ch. + +func drain() { + defer close(drainDone) + + batch := make([]entry, 0, 64) + ticker := time.NewTicker(250 * time.Millisecond) + defer ticker.Stop() + + flush := func() { + if len(batch) == 0 { + return + } + writeBatchToDB(batch) + batch = batch[:0] } - // 3. Write to DB using GORM. It handles its own connection pooling and locking. - if DB != nil { - var entry db.Log - entry.Timestamp = now.UnixMilli() - entry.Level = level.String() - entry.Message = message + for { + select { - // Use Save() to insert the new record. - result := DB.Save(&entry) - if result.Error != nil { - console.Printf("Failed to write log to database: %v\n", result.Error) + // New log entry + case e := <-ch: + writeToFile(e) + if db_ != nil { + batch = append(batch, e) + if len(batch) >= 64 { + flush() + } + } + + // Periodic DB flush so low-volume logs don't sit in the batch forever + case <-ticker.C: + flush() + + // Hot-swap the file backend + case f := <-fileSwapCh: + if file != nil { + file.Close() + } + file = f + + // Hot-swap the DB backend + case d := <-dbSwapCh: + flush() // flush any pending entries to the old db first + db_ = d + console.Println("logger: database backend attached") + + // Shutdown: drain what's left, then exit + case <-done: + // Pull any entries still sitting in the channel + for len(ch) > 0 { + e := <-ch + writeToFile(e) + batch = append(batch, e) + } + flush() + return } } } -func Debug(format string, args ...any) { logMsg(LevelDebug, format, args...) } -func Info(format string, args ...any) { logMsg(LevelInfo, format, args...) } -func Warning(format string, args ...any) { logMsg(LevelWarning, format, args...) } -func Error(format string, args ...any) { logMsg(LevelError, format, args...) } +// ─── Writers (called only from drain goroutine) ─────────────────────────────── -func Fatal(format string, args ...any) { - logMsg(LevelFatal, format, args...) - time.Sleep(100 * time.Millisecond) - os.Exit(1) +func writeToFile(e entry) { + line := formatLine(e) + if file != nil { + fmt.Fprintln(file, line) + } } + +func writeBatchToDB(batch []entry) { + if db_ == nil || len(batch) == 0 { + return + } + records := make([]db.Log, len(batch)) + for i, e := range batch { + records[i] = db.Log{ + Timestamp: e.timestamp.UnixMilli(), + Level: e.level.String(), + Message: e.message, + } + } + // Single INSERT ... VALUES (...), (...), (...) instead of N individual saves. + if result := db_.CreateInBatches(records, 64); result.Error != nil { + console.Printf("logger: db batch write failed: %v\n", result.Error) + } +} + +func formatLine(e entry) string { + return fmt.Sprintf("%s [%s] %s", + e.timestamp.Format("2006-01-02 15:04:05.000"), + e.level, + e.message, + ) +} + +// ─── Public API ─────────────────────────────────────────────────────────────── + +func logMsg(level Level, fatal bool, format string, args ...any) { + if level == LevelDebug && SetLevel != LevelDebug { + return + } + e := entry{ + level: level, + message: fmt.Sprintf(format, args...), + timestamp: time.Now(), // captured here, in the caller's goroutine + fatal: fatal, + } + + // Console is synchronous — log.Logger is internally mutex-protected, + // so this is safe from any goroutine and gives you immediate output. + console.Println(formatLine(e)) + + // Non-blocking send: if the buffer is full, we drop rather than deadlock. + // 4096 entries of headroom means this should never happen in practice. + select { + case ch <- e: + default: + console.Println("logger: channel full, entry dropped") + } + + if fatal { + // Give the drain goroutine a moment to flush before we exit. + // Close() is cleaner but Fatal has to exit immediately. + time.Sleep(150 * time.Millisecond) + os.Exit(1) + } +} + +func Debug(format string, args ...any) { logMsg(LevelDebug, false, format, args...) } +func Info(format string, args ...any) { logMsg(LevelInfo, false, format, args...) } +func Warning(format string, args ...any) { logMsg(LevelWarning, false, format, args...) } +func Error(format string, args ...any) { logMsg(LevelError, false, format, args...) } +func Fatal(format string, args ...any) { logMsg(LevelFatal, true, format, args...) } diff --git a/internal/mixer/mixer.go b/internal/mixer/mixer.go index 8977c00..e3a0cb9 100644 --- a/internal/mixer/mixer.go +++ b/internal/mixer/mixer.go @@ -70,7 +70,7 @@ func Init(cfg *db.AppConfig, onUpdate func()) error { return err } - SetAllSinkVolumes(1.0) + SetAllSinkVolumes(0.20) inited = true return nil diff --git a/internal/network/network.go b/internal/network/network.go index 5a8589c..629aa1c 100644 --- a/internal/network/network.go +++ b/internal/network/network.go @@ -1,603 +1,500 @@ -// Package network provides a high-level utility for managing network -// connections via the system's D-Bus and NetworkManager. package network import ( - "errors" + "context" "fmt" "net" - "sort" - "strings" - "sync" + "net/http" "time" - "github.com/godbus/dbus/v5" - "github.com/google/uuid" + gonm "github.com/Wifx/gonetworkmanager/v2" "rhemawavetech.com/rhemawave/internal/logger" ) -// --- D-Bus NetworkManager Constants --- -const ( - nmService = "org.freedesktop.NetworkManager" - nmPath = "/org/freedesktop/NetworkManager" - nmInterface = "org.freedesktop.NetworkManager" - nmDeviceInterface = "org.freedesktop.NetworkManager.Device" - nmWirelessDeviceInterface = "org.freedesktop.NetworkManager.Device.Wireless" - nmAPInterface = "org.freedesktop.NetworkManager.AccessPoint" +// ─── Public types ───────────────────────────────────────────────────────────── - nmDeviceTypeEthernet uint32 = 1 - nmDeviceTypeWifi uint32 = 2 - nmDeviceStateActivated uint32 = 100 - APFlagsPrivacy uint32 = 0x00000001 // Equivalent to NM_802_11_AP_FLAGS_PRIVACY - - // Device states (from NM spec) - // nmDeviceStateUnknown uint32 = 0 - nmDeviceStateUnmanaged uint32 = 10 - nmDeviceStateUnavailable uint32 = 20 - // nmDeviceStateDisconnected uint32 = 30 - nmDeviceStateFailed uint32 = 120 - - // AP Security Flags (from NM_802_11_AP_SEC_*) - APFlagsWpaPsk uint32 = 0x00000100 // WPA-Personal - APFlagsWpaEap uint32 = 0x00000200 // WPA-Enterprise - APFlagsRsnPsk uint32 = 0x00000100 // WPA2-Personal (same flag as WPA-PSK) - APFlagsRsnSae uint32 = 0x00000400 // WPA3-Personal (SAE) - APFlagsRsnEap uint32 = 0x00000200 // WPA2-Enterprise (same flag as WPA-EAP) - APFlagsRsnOwe uint32 = 0x00000800 // OWE (Opportunistic Wireless Encryption) - APFlagsRsnEapSuiteB uint32 = 0x00001000 // WPA3-Enterprise -) - -// ErrScanAborted is returned when a scan is cancelled via the stop channel. -var ErrScanAborted = errors.New("network scan aborted by caller") - -// Status defines the type for various connection status codes. -type Status int +type SecurityType string const ( - StatusError Status = iota - StatusNoDevicesFound - StatusWifiAvailableNotConnected - StatusWifiConnectedNoInternet - StatusWifiConnectedInternetUp - StatusEthernetNotConnected - StatusEthernetConnectedNoInternet - StatusEthernetConnectedInternetUp + SecurityOpen SecurityType = "Open" + SecurityWEP SecurityType = "WEP" + SecurityWPA SecurityType = "WPA" + SecurityWPA2 SecurityType = "WPA2" + SecurityWPA3 SecurityType = "WPA3" ) -// ConnectionStatus holds the detailed result of a connectivity check. -type ConnectionStatus struct { - StatusCode Status - Message string +type Network struct { + SSID string + SignalStrength uint8 + Security SecurityType + Saved bool + Connected bool } -// DeviceType defines the kind of network device. -type DeviceType int +// ─── Package init ───────────────────────────────────────────────────────────── -const ( - TypeUnknown DeviceType = iota - TypeEthernet - TypeWifi -) +var nm gonm.NetworkManager -// Device holds information about a single network device. -type Device struct { - Path dbus.ObjectPath - InterfaceName string - Type DeviceType - State uint32 -} - -// Manager handles all D-Bus communication with NetworkManager. -type Manager struct { - conn *dbus.Conn - nmObject dbus.BusObject - Devices []Device - mu sync.RWMutex // protects Devices -} - -// AccessPoint holds essential information about a discovered Wi-Fi network. -type AccessPoint struct { - ObjectPath dbus.ObjectPath - SSID string - Strength byte - IsProtected bool - IsActive bool - KeyMgmt string -} - -// New creates a new network Manager and connects to the system D-Bus. -func New() (*Manager, error) { - logger.Info("[NET-001] Initializing NetworkManager client") - logger.Debug("[NET-002] Connecting to system D-Bus") - conn, err := dbus.ConnectSystemBus() +func init() { + var err error + nm, err = gonm.NewNetworkManager() if err != nil { - logger.Error("failed to connect to system bus: %v", err) - return nil, fmt.Errorf("failed to connect to system bus: %w", err) + fmt.Printf("network: failed to connect to NetworkManager: %v\n", err) } - nmObject := conn.Object(nmService, nmPath) - logger.Debug("network manager created") - return &Manager{conn: conn, nmObject: nmObject}, nil } -// Conn returns the underlying dbus.Conn for advanced queries. -func (m *Manager) Conn() *dbus.Conn { - logger.Debug("[NET-010] Returning underlying D-Bus connection") - logger.Debug("Conn() returning m.conn") - return m.conn -} +// ─── ScanForNetworks ────────────────────────────────────────────────────────── -// Close disconnects from the D-Bus. -func (m *Manager) Close() { - logger.Info("[NET-020] Closing NetworkManager client") - logger.Debug("Disconnecting from the D-Bus") - if m.conn != nil { - m.conn.Close() - logger.Debug("Disconnected") - } - logger.Debug("Nothing to disconnect!") -} - -// FindDevices scans the system for all available network devices (Ethernet and Wi-Fi). -func (m *Manager) FindDevices() error { - logger.Info("[NET-030] Starting network device discovery") - logger.Debug("Searching for network devices") - var devicePaths []dbus.ObjectPath - call := m.nmObject.Call(nmInterface+".GetDevices", 0) - if call.Err != nil { - logger.Error("GetDevices D-Bus call failed: %v", call.Err) - return fmt.Errorf("GetDevices D-Bus call failed: %w", call.Err) - } - if err := call.Store(&devicePaths); err != nil { - return fmt.Errorf("could not parse device list: %w", err) +func ScanForNetworks(ctx context.Context) (<-chan []Network, error) { + dev, err := wifiDevice() + if err != nil { + return nil, err } - m.Devices = []Device{} - for _, path := range devicePaths { - deviceObj := m.conn.Object(nmService, path) - typeVariant, err := deviceObj.GetProperty(nmDeviceInterface + ".DeviceType") - if err != nil { - logger.Warning("[NET-031] Skipping device %s because DeviceType could not be read: %v", path, err) - continue - } - deviceType, ok := typeVariant.Value().(uint32) - if !ok { - logger.Warning("[NET-032] Skipping device %s because DeviceType was invalid", path) - continue - } + ch := make(chan []Network, 1) - var newDevice Device - switch deviceType { - case nmDeviceTypeEthernet: - newDevice.Type = TypeEthernet - case nmDeviceTypeWifi: - newDevice.Type = TypeWifi - default: - continue - } + go func() { + defer close(ch) - newDevice.Path = path + ticker := time.NewTicker(15 * time.Second) + defer ticker.Stop() - // Safely get Interface property - ifaceVariant, err := deviceObj.GetProperty(nmDeviceInterface + ".Interface") - if err != nil { - logger.Warning("[NET-033] Skipping device %s because Interface property could not be read: %v", path, err) - continue - } - if newDevice.InterfaceName, ok = ifaceVariant.Value().(string); !ok { - logger.Warning("[NET-034] Skipping device %s because Interface property was invalid", path) - continue - } + scan := func() { + if err := dev.RequestScan(); err != nil { + logger.Warning("network: scan request failed: %v", err) + return + } + time.Sleep(2 * time.Second) - // Safely get State property - stateVariant, err := deviceObj.GetProperty(nmDeviceInterface + ".State") - if err != nil { - logger.Warning("[NET-035] Skipping device %s because State property could not be read: %v", path, err) - continue - } - if newDevice.State, ok = stateVariant.Value().(uint32); !ok { - logger.Warning("[NET-036] Skipping device %s because State property was invalid", path) - continue - } - - m.Devices = append(m.Devices, newDevice) - } - return nil -} - -// CheckInternetConnection performs a check for an active internet connection. -func (m *Manager) CheckInternetConnection() (*ConnectionStatus, error) { - logger.Debug("[NET-040] Checking internet connectivity") - - // Previously called FindDevices() here, which rebuilt m.Devices every 2s, - // causing [NET-030] log spam and invalidating any pointers held by callers. - // Device enumeration is done once in Init(); we only need fresh State values. - // If this is a fresh Manager with no devices yet (e.g. called from - // checkState which creates a new Manager each tick), do a full device - // discovery. If devices are already known (e.g. the WiFiSetupPage's - // long-lived Manager), only refresh State to avoid the [NET-030] spam - // and avoid rebuilding the slice which would invalidate held pointers. - if len(m.Devices) == 0 { - if err := m.FindDevices(); err != nil { - return &ConnectionStatus{StatusError, "Failed to scan devices"}, err - } - } else { - m.mu.Lock() - for i := range m.Devices { - deviceObj := m.conn.Object(nmService, m.Devices[i].Path) - stateVariant, err := deviceObj.GetProperty(nmDeviceInterface + ".State") + nets, err := buildNetworkList(dev) if err != nil { - logger.Warning("[NET-041] Could not refresh state for device %s: %v", m.Devices[i].Path, err) - continue + logger.Warning("network: building network list failed: %v", err) + return } - if state, ok := stateVariant.Value().(uint32); ok { - m.Devices[i].State = state + + select { + case ch <- nets: + case <-ctx.Done(): } } - m.mu.Unlock() - } - // Check Ethernet first (Priority) - for _, device := range m.Devices { - if device.Type == TypeEthernet && device.State == nmDeviceStateActivated { - if pingTest() { - return &ConnectionStatus{StatusEthernetConnectedInternetUp, "Ethernet: Online"}, nil + scan() + + for { + select { + case <-ticker.C: + scan() + case <-ctx.Done(): + return } - return &ConnectionStatus{StatusEthernetConnectedNoInternet, "Ethernet: No Internet"}, nil } - } + }() - // Check Wifi - for _, device := range m.Devices { - if device.Type == TypeWifi && device.State == nmDeviceStateActivated { - if pingTest() { - return &ConnectionStatus{StatusWifiConnectedInternetUp, "Wi-Fi: Online"}, nil - } - // Even if ping fails, the state IS activated (connected to AP) - return &ConnectionStatus{StatusWifiConnectedNoInternet, "Wi-Fi: Connected, checking internet..."}, nil - } - } - - return &ConnectionStatus{StatusWifiAvailableNotConnected, "Ready to connect"}, nil + return ch, nil } -// StartScan performs a Wi-Fi scan asynchronously. The optional stopChan can be used to abort. -func (m *Manager) StartScan(resultsChan chan<- []AccessPoint, errorChan chan<- error, stopChan <-chan struct{}) { - - logger.Info("[NET-050] Starting Wi‑Fi scan") - - m.mu.RLock() - - var wifiDevice *Device - - for i := range m.Devices { - if m.Devices[i].Type == TypeWifi { - wifiDevice = &m.Devices[i] - break - } - } - - m.mu.RUnlock() - - if wifiDevice == nil { - errorChan <- fmt.Errorf("no Wi-Fi device available for scanning") - return - } - - // Ensure Wi-Fi is enabled - nmObj := m.conn.Object(nmService, nmPath) - - prop, err := nmObj.GetProperty(nmInterface + ".WirelessEnabled") +// ─── ConnectToNetwork ───────────────────────────────────────────────────────── +func ConnectToNetwork(ssid, password string) error { + dev, err := wifiDevice() if err != nil { - errorChan <- fmt.Errorf("could not read WirelessEnabled property: %w", err) - return + return err } - if !prop.Value().(bool) { - - call := nmObj.Call("org.freedesktop.DBus.Properties.Set", 0, - nmInterface, - "WirelessEnabled", - dbus.MakeVariant(true), - ) - - if call.Err != nil { - errorChan <- fmt.Errorf("could not enable Wi-Fi: %w", call.Err) - return - } - - time.Sleep(2 * time.Second) // Give NetworkManager time to bring up the device - } - - // Request a scan - wifiDeviceWireless := m.conn.Object(nmService, wifiDevice.Path) - - call := wifiDeviceWireless.Call(nmWirelessDeviceInterface+".RequestScan", 0, make(map[string]dbus.Variant)) - - if call.Err != nil { - errorChan <- fmt.Errorf("scan request failed: %w", call.Err) - return - } - - select { - case <-time.After(3 * time.Second): - case <-stopChan: - errorChan <- ErrScanAborted - return - } - - var apPaths []dbus.ObjectPath - - call = wifiDeviceWireless.Call(nmWirelessDeviceInterface+".GetAllAccessPoints", 0) - - if call.Err != nil { - errorChan <- fmt.Errorf("could not retrieve network list: %w", call.Err) - return - } - - if err := call.Store(&apPaths); err != nil { - errorChan <- fmt.Errorf("could not parse network list: %w", err) - return - } - - processedAPs, err := m.scanAccessPoints(apPaths) + ap, err := findAccessPoint(dev, ssid) if err != nil { - errorChan <- err - return + return fmt.Errorf("network: access point %q not found: %w", ssid, err) } - resultsChan <- processedAPs + security := detectSecurity(ap) + settings, err := buildConnectionSettings(ssid, password, security) + if err != nil { + return err + } + + logger.Info("network: connecting to %q (%s)", ssid, security) + + _, err = nm.AddAndActivateConnection(settings, dev) + if err != nil { + return fmt.Errorf("network: failed to connect to %q: %w", ssid, err) + } + + return waitForConnection(ssid, 15*time.Second) } -// scanAccessPoints filters and sorts the raw list of D-Bus AP paths. -func (m *Manager) scanAccessPoints(apPaths []dbus.ObjectPath) ([]AccessPoint, error) { - logger.Debug("[NET-060] Processing %d access points", len(apPaths)) - tempNetworkMap := make(map[string]AccessPoint) - for _, apPath := range apPaths { - apObj := m.conn.Object(nmService, apPath) - props, err := m.getAllProperties(apObj, nmAPInterface) +// ─── ForgetNetwork ──────────────────────────────────────────────────────────── + +func ForgetNetwork(ssid string) error { + s, err := gonm.NewSettings() + if err != nil { + return fmt.Errorf("network: cannot access NM settings: %w", err) + } + + connections, err := s.ListConnections() + if err != nil { + return fmt.Errorf("network: cannot list connections: %w", err) + } + + found := false + for _, conn := range connections { + settings, err := conn.GetSettings() if err != nil { - logger.Warning("[NET-061] Failed to read access point properties for %s: %v", apPath, err) + continue + } + wireless, ok := settings["802-11-wireless"] + if !ok { + continue + } + rawSSID, ok := wireless["ssid"] + if !ok { + continue + } + if string(rawSSID.([]byte)) != ssid { continue } - ssidBytes, ok := props["Ssid"].Value().([]byte) - if !ok || len(ssidBytes) == 0 { - continue - } - - ssidStr := string(ssidBytes) - strength, _ := props["Strength"].Value().(byte) - flags, _ := props["Flags"].Value().(uint32) - wpaFlags, _ := props["WpaFlags"].Value().(uint32) - rsnFlags, _ := props["RsnFlags"].Value().(uint32) - - isProtected := (flags&APFlagsPrivacy != 0) || (wpaFlags != 0) || (rsnFlags != 0) - - // Determine key management type - var keyMgmt string - if !isProtected { - keyMgmt = "none" - } else if wpaFlags != 0 { - // WPA (not WPA2/WPA3) - if wpaFlags&APFlagsWpaPsk != 0 { - keyMgmt = "wpa-psk" - } else if wpaFlags&APFlagsWpaEap != 0 { - keyMgmt = "wpa-eap" - } else { - keyMgmt = "wpa-psk" // Fallback - } - } else if rsnFlags != 0 { - // WPA2 or WPA3 (RSN) - if rsnFlags&APFlagsRsnSae != 0 { - keyMgmt = "sae" // WPA3-Personal - } else if rsnFlags&APFlagsRsnEapSuiteB != 0 { - keyMgmt = "eap-suite-b-192" // WPA3-Enterprise - } else if rsnFlags&APFlagsRsnEap != 0 { - keyMgmt = "wpa-eap" // WPA2-Enterprise - } else { - keyMgmt = "wpa-psk" // WPA2-Personal (default for RSN) - } - } else { - keyMgmt = "none" - } - - currentAP := AccessPoint{ - ObjectPath: apPath, - SSID: ssidStr, - Strength: strength, - IsProtected: isProtected, - KeyMgmt: keyMgmt, - } - if existingAP, ok := tempNetworkMap[ssidStr]; !ok || strength > existingAP.Strength { - tempNetworkMap[ssidStr] = currentAP + found = true + logger.Info("network: forgetting %q", ssid) + if err := conn.Delete(); err != nil { + return fmt.Errorf("network: failed to delete connection %q: %w", ssid, err) } } - networkList := make([]AccessPoint, 0, len(tempNetworkMap)) - for _, ap := range tempNetworkMap { - networkList = append(networkList, ap) + if !found { + return fmt.Errorf("network: no saved connection found for %q", ssid) } - sort.Slice(networkList, func(i, j int) bool { - if networkList[i].Strength != networkList[j].Strength { - return networkList[i].Strength > networkList[j].Strength - } - return strings.ToLower(networkList[i].SSID) < strings.ToLower(networkList[j].SSID) - }) - return networkList, nil -} - -// Connect attempts to connect a Wi-Fi device to a given access point. -func (m *Manager) Connect(wifiDevice Device, ap AccessPoint, passphrase string) error { - logger.Info("[NET-070] Connection requested for SSID %q using adapter %q", ap.SSID, wifiDevice.InterfaceName) - if wifiDevice.Type != TypeWifi { - return fmt.Errorf("cannot connect: provided device is not a Wi-Fi device") - } - m.mu.RLock() - currentState := wifiDevice.State - for _, d := range m.Devices { - if d.Path == wifiDevice.Path { - currentState = d.State - break - } - } - m.mu.RUnlock() - - if currentState == nmDeviceStateFailed || - currentState == nmDeviceStateUnmanaged || - currentState == nmDeviceStateUnavailable { - return fmt.Errorf("cannot connect: device is in an error state (state=%d)", currentState) - } - - // Delete any existing NM connection profile for this SSID to avoid - // accumulating duplicates across connection attempts. - settingsObj := m.conn.Object(nmService, "/org/freedesktop/NetworkManager/Settings") - var existingPaths []dbus.ObjectPath - if call := settingsObj.Call("org.freedesktop.NetworkManager.Settings.ListConnections", 0); call.Err == nil { - _ = call.Store(&existingPaths) - for _, cp := range existingPaths { - cObj := m.conn.Object(nmService, cp) - var csettings map[string]map[string]dbus.Variant - if c2 := cObj.Call("org.freedesktop.NetworkManager.Settings.Connection.GetSettings", 0); c2.Err == nil { - if err := c2.Store(&csettings); err == nil { - if id, ok := csettings["connection"]["id"].Value().(string); ok && id == ap.SSID { - logger.Info("[NET-073] Deleting existing profile for %q before reconnect", ap.SSID) - _ = cObj.Call("org.freedesktop.NetworkManager.Settings.Connection.Delete", 0) - } - } - } - } - } - - settings := map[string]map[string]dbus.Variant{ - "connection": { - "type": dbus.MakeVariant("802-11-wireless"), - "uuid": dbus.MakeVariant(uuid.NewString()), - "id": dbus.MakeVariant(ap.SSID), - "interface-name": dbus.MakeVariant(wifiDevice.InterfaceName), - "permissions": dbus.MakeVariant([]string{}), // Shared connection - "autoconnect": dbus.MakeVariant(true), - }, - "802-11-wireless": { - "ssid": dbus.MakeVariant([]byte(ap.SSID)), - "mode": dbus.MakeVariant("infrastructure"), - }, - "ipv4": {"method": dbus.MakeVariant("auto")}, - "ipv6": {"method": dbus.MakeVariant("auto")}, - } - - if ap.IsProtected { - settings["802-11-wireless-security"] = map[string]dbus.Variant{ - "key-mgmt": dbus.MakeVariant(ap.KeyMgmt), - "auth-alg": dbus.MakeVariant("open"), - "psk": dbus.MakeVariant(passphrase), - } - // 0 means "The secret is not saved or is managed by an external agent" - // In a kiosk, we want NM to just handle it. - settings["802-11-wireless-security"]["psk-flags"] = dbus.MakeVariant(uint32(0)) - } - - var connectionPath dbus.ObjectPath - var activeConnectionPath dbus.ObjectPath - - // Capture the two return values from AddAndActivateConnection - err := m.nmObject.Call(nmInterface+".AddAndActivateConnection", 0, settings, wifiDevice.Path, ap.ObjectPath).Store(&connectionPath, &activeConnectionPath) - - if err != nil { - // THIS IS THE LOG YOU NEED TO SEE IN SSH - logger.Error("[NET-071] NetworkManager rejected the connection request: %v", err) - return fmt.Errorf("AddAndActivateConnection failed: %w", err) - } - - logger.Info("[NET-072] Connection created successfully. Connection=%s Active=%s", connectionPath, activeConnectionPath) - - // Removed WaitForInternet() call here. It blocked the caller's thread - // for up to 35s and returned an error even on successful NM initiation - // if internet wasn't stable in time. The page's checkConnectionStatusLoop - // and handleConnectionStatusUpdate handle post-connection state tracking. - logger.Info("[NET-072] Connection initiated. Connection=%s Active=%s", connectionPath, activeConnectionPath) return nil } -// pingTest with a short timeout to prevent the UI loop from hanging -func pingTest() bool { - logger.Debug("[NET-080] Beginning internet reachability test") - targets := []string{ - "1.1.1.1:53", // Cloudflare DNS - "8.8.8.8:53", // Google DNS - "9.9.9.9:53", // Quad9 DNS - "149.112.112.112:53", // Quad9 Alternate +// ─── CurrentNetwork ─────────────────────────────────────────────────────────── + +func CurrentNetwork() (string, error) { + dev, err := wifiDevice() + if err != nil { + return "", err } - timeout := 2 * time.Second + + ap, err := dev.GetPropertyActiveAccessPoint() + if err != nil || ap == nil { + return "", nil + } + + ssid, err := ap.GetPropertySSID() + if err != nil { + return "", err + } + + return ssid, nil +} + +// ─── ListSavedNetworks ──────────────────────────────────────────────────────── + +func ListSavedNetworks() ([]string, error) { + s, err := gonm.NewSettings() + if err != nil { + return nil, fmt.Errorf("network: cannot access NM settings: %w", err) + } + + connections, err := s.ListConnections() + if err != nil { + return nil, fmt.Errorf("network: cannot list connections: %w", err) + } + + var ssids []string + for _, conn := range connections { + settings, err := conn.GetSettings() + if err != nil { + continue + } + wireless, ok := settings["802-11-wireless"] + if !ok { + continue + } + rawSSID, ok := wireless["ssid"] + if !ok { + continue + } + ssids = append(ssids, string(rawSSID.([]byte))) + } + + return ssids, nil +} + +// ─── IsConnected ────────────────────────────────────────────────────────────── + +func IsConnected() (bool, error) { + if nm == nil { + return false, fmt.Errorf("network: NetworkManager not available") + } + + state, err := nm.GetPropertyState() + if err != nil { + return false, fmt.Errorf("network: cannot get NM state: %w", err) + } + + return state >= gonm.NmStateConnectedLocal, nil +} + +// ─── HasInternet ────────────────────────────────────────────────────────────── + +func HasInternet() bool { + targets := []string{ + "1.1.1.1:53", + "1.0.0.1:53", + "8.8.8.8:53", + "9.9.9.9:53", + "8.8.4.4:53", + "google.com:443", + "cloudflare.com:443", + } + + results := make(chan bool, len(targets)) for _, target := range targets { - conn, err := net.DialTimeout("tcp", target, timeout) - if err == nil { - conn.Close() + go func(addr string) { + conn, err := net.DialTimeout("tcp", addr, 2*time.Second) + if err == nil { + conn.Close() + results <- true + } else { + results <- false + } + }(target) + } + + for range targets { + if <-results { return true } } return false } -// getAllProperties is a helper to fetch all properties for a D-Bus object interface. -func (m *Manager) getAllProperties(obj dbus.BusObject, iface string) (map[string]dbus.Variant, error) { - logger.Debug("[NET-090] Fetching all D‑Bus properties for interface %s", iface) - var props map[string]dbus.Variant - call := obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, iface) - if call.Err != nil { - return nil, call.Err +// ─── WatchState ─────────────────────────────────────────────────────────────── + +func WatchState(ctx context.Context) (<-chan bool, error) { + if nm == nil { + return nil, fmt.Errorf("network: NetworkManager not available") } - if err := call.Store(&props); err != nil { - return nil, err - } - return props, nil -} -// WaitForInternet blocks until CheckInternetConnection reports Internet up, -// or until maxWait elapses. When it first sees "up", it requires that state -// to be stable for at least 'stableFor' before returning success to avoid flapping. -func (m *Manager) WaitForInternet(maxWait, stableFor time.Duration) (*ConnectionStatus, error) { - logger.Info("[NET-100] Waiting for internet connectivity (maxWait=%s stableFor=%s)", maxWait, stableFor) - deadline := time.Now().Add(maxWait) - var lastErr error - var lastStatus *ConnectionStatus - var upSince time.Time + ch := make(chan bool, 1) - // Reasonable poll cadence; NM typically completes within a few seconds. - const poll = 500 * time.Millisecond + go func() { + defer close(ch) - for time.Now().Before(deadline) { - st, err := m.CheckInternetConnection() - if err != nil { - lastErr = err - lastStatus = &ConnectionStatus{StatusError, "NetworkManager not ready"} - upSince = time.Time{} // reset stability - } else { - lastStatus = st - switch st.StatusCode { - case StatusEthernetConnectedInternetUp, StatusWifiConnectedInternetUp: - if upSince.IsZero() { - upSince = time.Now() + ticker := time.NewTicker(3 * time.Second) + defer ticker.Stop() + + var last *bool + + for { + select { + case <-ticker.C: + connected, err := IsConnected() + if err != nil { + logger.Warning("network: WatchState poll failed: %v", err) + continue } - if time.Since(upSince) >= stableFor { - return st, nil // stable "up" + if last == nil || *last != connected { + last = &connected + select { + case ch <- connected: + case <-ctx.Done(): + return + } } - default: - // not up; keep waiting - upSince = time.Time{} + case <-ctx.Done(): + return } } - time.Sleep(poll) + }() + + return ch, nil +} + +// ─── Internal helpers ───────────────────────────────────────────────────────── + +func wifiDevice() (gonm.DeviceWireless, error) { + if nm == nil { + return nil, fmt.Errorf("network: NetworkManager not available") } - // Timed out; return the last observed status and error (if any). - if lastStatus == nil { - lastStatus = &ConnectionStatus{StatusError, "Timed out waiting for connectivity"} + devices, err := nm.GetPropertyAllDevices() + if err != nil { + return nil, fmt.Errorf("network: cannot list devices: %w", err) } - if lastErr != nil { - return lastStatus, fmt.Errorf("timeout waiting for internet: %w", lastErr) + + for _, dev := range devices { + devType, err := dev.GetPropertyDeviceType() + if err != nil { + continue + } + if devType == gonm.NmDeviceTypeWifi { + return gonm.NewDeviceWireless(dev.GetPath()) + } } - return lastStatus, nil + + return nil, fmt.Errorf("network: no WiFi device found") } + +func findAccessPoint(dev gonm.DeviceWireless, ssid string) (gonm.AccessPoint, error) { + aps, err := dev.GetPropertyAccessPoints() + if err != nil { + return nil, err + } + + for _, ap := range aps { + apSSID, err := ap.GetPropertySSID() + if err != nil { + continue + } + if apSSID == ssid { + return ap, nil + } + } + + return nil, fmt.Errorf("not found") +} + +func detectSecurity(ap gonm.AccessPoint) SecurityType { + flags, _ := ap.GetPropertyFlags() + wpaFlags, _ := ap.GetPropertyWPAFlags() + rsnFlags, _ := ap.GetPropertyRSNFlags() + + if rsnFlags != 0 { + if rsnFlags&0x100 != 0 { + return SecurityWPA3 + } + return SecurityWPA2 + } + if wpaFlags != 0 { + return SecurityWPA + } + if flags&0x1 != 0 { + return SecurityWEP + } + + return SecurityOpen +} + +func buildConnectionSettings(ssid, password string, security SecurityType) (map[string]map[string]interface{}, error) { + settings := map[string]map[string]interface{}{ + "connection": { + "id": ssid, + "type": "802-11-wireless", + }, + "802-11-wireless": { + "ssid": []byte(ssid), + "mode": "infrastructure", + }, + "ipv4": {"method": "auto"}, + "ipv6": {"method": "auto"}, + } + + switch security { + case SecurityOpen: + // nothing + + case SecurityWEP: + if password == "" { + return nil, fmt.Errorf("network: WEP network requires a password") + } + settings["802-11-wireless-security"] = map[string]interface{}{ + "key-mgmt": "none", + "wep-key0": password, + "wep-key-type": uint32(1), + } + + case SecurityWPA, SecurityWPA2: + if password == "" { + return nil, fmt.Errorf("network: WPA/WPA2 network requires a password") + } + settings["802-11-wireless-security"] = map[string]interface{}{ + "key-mgmt": "wpa-psk", + "psk": password, + } + + case SecurityWPA3: + if password == "" { + return nil, fmt.Errorf("network: WPA3 network requires a password") + } + settings["802-11-wireless-security"] = map[string]interface{}{ + "key-mgmt": "sae", + "psk": password, + } + } + + return settings, nil +} + +func buildNetworkList(dev gonm.DeviceWireless) ([]Network, error) { + aps, err := dev.GetPropertyAccessPoints() + if err != nil { + return nil, err + } + + activeAP, _ := dev.GetPropertyActiveAccessPoint() + var activeSSID string + if activeAP != nil { + activeSSID, _ = activeAP.GetPropertySSID() + } + + saved, _ := ListSavedNetworks() + savedSet := make(map[string]bool, len(saved)) + for _, s := range saved { + savedSet[s] = true + } + + var networks []Network + seen := make(map[string]bool) + + for _, ap := range aps { + ssid, err := ap.GetPropertySSID() + if err != nil || ssid == "" { + continue + } + if seen[ssid] { + continue + } + seen[ssid] = true + + strength, _ := ap.GetPropertyStrength() + + networks = append(networks, Network{ + SSID: ssid, + SignalStrength: strength, + Security: detectSecurity(ap), + Saved: savedSet[ssid], + Connected: ssid == activeSSID, + }) + } + + return networks, nil +} + +func waitForConnection(ssid string, timeout time.Duration) error { + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + current, err := CurrentNetwork() + if err == nil && current == ssid { + return nil + } + time.Sleep(500 * time.Millisecond) + } + return fmt.Errorf("network: timed out waiting for connection to %q", ssid) +} + +var internetCheckURL = "https://clients3.google.com/generate_204" + +func httpCheck() bool { + client := http.Client{Timeout: 3 * time.Second} + resp, err := client.Get(internetCheckURL) + if err != nil { + return false + } + resp.Body.Close() + return resp.StatusCode == 204 +} + +var _ = httpCheck diff --git a/internal/page/AudioOptions.go b/internal/page/AudioOptions.go index a59e7a2..acb6a4d 100644 --- a/internal/page/AudioOptions.go +++ b/internal/page/AudioOptions.go @@ -100,7 +100,7 @@ func (p *AudioOptions) Init(ctx *PageCtx) error { // Font fm := fontManager.Get() - font, ok := fm.GetFont("Roboto-Regular") + font, ok := fm.GetFont("SpaceMonoNerdFont-Regular") if !ok { return fmt.Errorf("failed to get font: %w", sdl.GetError()) } @@ -121,7 +121,12 @@ func (p *AudioOptions) Init(ctx *PageCtx) error { return fmt.Errorf("base init failed: %w", err) } - baseFontSize := p.Context.CfgPtr.StandardFontSize + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + + baseFontSize := config.StandardFontSize titleScale := float32(64) / float32(baseFontSize) p.ItemScale = float32(32) / float32(baseFontSize) @@ -211,7 +216,11 @@ func (p *AudioOptions) seedAudioFiles() error { // ── Audio status toggle ─────────────────────────────────────────────────────── func (p *AudioOptions) CreateAudioStatusItem() error { - on := p.Context.CfgPtr.AudioEnabled + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + on := config.AudioEnabled statusString := "Turn Audio On" color := colors.Green if on { @@ -277,7 +286,11 @@ func (p *AudioOptions) CreateVolumePercentItem() error { if p.volumePercent.ID != 0 { gl.DeleteTextures(1, &p.volumePercent.ID) } - pct := int(p.Context.CfgPtr.SavedVolume * 100) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + pct := int(config.SavedVolume * 100) item, err := NewStringItem(fmt.Sprintf("%d%%", pct), p.font, colors.White) if err != nil { return fmt.Errorf("failed to create volume percent item: %v", err) @@ -288,15 +301,19 @@ func (p *AudioOptions) CreateVolumePercentItem() error { } func (p *AudioOptions) UpdateVolume(level int) { - newVol := mixer.ConvertVolume(level) + p.Context.CfgPtr.SavedVolume + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + newVol := mixer.ConvertVolume(level) + config.SavedVolume if newVol < 0.0 || newVol > 1.0 { return } if newVol > .99 { newVol = 1.0 } - p.Context.CfgPtr.SavedVolume = newVol - p.Context.DbPtr.Save(&p.Context.CfgPtr) + config.SavedVolume = newVol + p.Context.DbPtr.Save(&config) if err := mixer.SetAllSinkVolumes(newVol); err != nil { logger.Error("Error setting allSinkVolumes: %v", err) } @@ -311,6 +328,11 @@ func (p *AudioOptions) UpdateVolume(level int) { // ── Layout ──────────────────────────────────────────────────────────────────── func (p *AudioOptions) layout() { + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + // Title p.title.X = p.ScreenCenterX - p.title.W/2 p.title.Y = p.ScreenHeight - p.title.H - p.verticalMargin*2 @@ -320,7 +342,7 @@ func (p *AudioOptions) layout() { p.prompt.Y = p.title.Y - p.verticalMargin - p.prompt.H // Volume row - barH := int32(float32(p.Context.CfgPtr.StandardFontSize) * p.ItemScale) + barH := int32(float32(config.StandardFontSize) * p.ItemScale) barW := int32(float32(p.ScreenWidth) * 0.30) barX := p.ScreenCenterX - barW/2 barY := p.prompt.Y - p.verticalMargin*2 - barH @@ -376,8 +398,12 @@ func (p *AudioOptions) updateCursorPosition() { // ── Toggle ──────────────────────────────────────────────────────────────────── func (p *AudioOptions) ToggleAudio() { - p.Context.CfgPtr.AudioEnabled = !p.Context.CfgPtr.AudioEnabled - p.Context.DbPtr.Save(p.Context.CfgPtr) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + config.AudioEnabled = !config.AudioEnabled + p.Context.DbPtr.Save(config) p.Context.RefreshConfig() p.CreateAudioStatusItem() p.layout() @@ -447,7 +473,11 @@ func (p *AudioOptions) Update(dt float32) error { // ── Render helpers ──────────────────────────────────────────────────────────── func (p *AudioOptions) renderVolumeBar() error { - vol := p.Context.CfgPtr.SavedVolume + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + vol := config.SavedVolume fillW := float32(p.volumeBarW) * float32(vol) if fillW > 0 { diff --git a/internal/page/emailAddressPage.go b/internal/page/emailAddressPage.go index 3465c09..14b274c 100644 --- a/internal/page/emailAddressPage.go +++ b/internal/page/emailAddressPage.go @@ -8,6 +8,7 @@ import ( "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" + "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/shaderManager" ) @@ -59,7 +60,7 @@ func (p *EmailAddressPage) Init(ctx *PageCtx) error { p.title = "Your Email Address" - applicationFont := "Roboto-Regular" + applicationFont := "SpaceMonoNerdFont-Regular" fm := fontManager.Get() textShader, ok := shaderManager.Get().Get("text") @@ -81,7 +82,11 @@ func (p *EmailAddressPage) Init(ctx *PageCtx) error { p.titleTextureHeight = titleHeight // Load existing email address from database - emailAddress := ctx.CfgPtr.EmailAddress + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + emailAddress := config.EmailAddress if emailAddress != "" { p.inputText = emailAddress @@ -154,9 +159,12 @@ func (p *EmailAddressPage) HandleEvent(event *sdl.Event) error { sdl.StopTextInput() // Save email address to database - p.Context.CfgPtr.EmailAddress = p.inputText - p.Context.DbPtr.Save(p.Context.CfgPtr) - p.Context.RefreshConfig() + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + config.EmailAddress = p.inputText + p.Context.DbPtr.Save(config) if p.isFirstTimeSetup { // First-time setup: navigate to License Key page @@ -189,7 +197,7 @@ func (p *EmailAddressPage) HandleEvent(event *sdl.Event) error { // Update updates animations and changing textures and other changes using `dt` which represents a time delta in float32. func (p *EmailAddressPage) Update(dt float32) error { // Get application font from database - applicationFont := "Roboto-Regular" + applicationFont := "SpaceMonoNerdFont-Regular" fm := fontManager.Get() sm := shaderManager.Get() @@ -252,8 +260,12 @@ func (p *EmailAddressPage) Update(dt float32) error { // Render performs page drawing logic. func (p *EmailAddressPage) Render() error { + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } // Get base font size from database - baseFontSize := p.Context.CfgPtr.StandardFontSize + baseFontSize := config.StandardFontSize sm := shaderManager.Get() diff --git a/internal/page/home.go b/internal/page/home.go index b6253e2..699a9f2 100644 --- a/internal/page/home.go +++ b/internal/page/home.go @@ -7,12 +7,13 @@ import ( "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" + "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/download" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/shaderManager" ) -var GitVersion = "cd79a6f" +var GitVersion = "9beeeb1" type Home struct { Base @@ -45,7 +46,7 @@ func (p *Home) Init(ctx *PageCtx) error { // Get font p.fm = fontManager.Get() - font, ok := p.fm.GetFont("Roboto-Regular") + font, ok := p.fm.GetFont("SpaceMonoNerdFont-Regular") if !ok { return fmt.Errorf("unable to fetch font") } @@ -86,8 +87,13 @@ func (p *Home) Init(ctx *PageCtx) error { return fmt.Errorf("unable to create initial message texture: %w", err) } + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + // Create license info textures if data exists - if p.Context.CfgPtr.EmailAddress != "" || p.Context.CfgPtr.LicenseKey != "" { + if config.EmailAddress != "" || config.LicenseKey != "" { p.hasLicenseInfo = true // Create heading @@ -97,8 +103,8 @@ func (p *Home) Init(ctx *PageCtx) error { } // Create email display if exists - if p.Context.CfgPtr.EmailAddress != "" { - emailText := fmt.Sprintf("Email: %s", p.Context.CfgPtr.EmailAddress) + if config.EmailAddress != "" { + emailText := fmt.Sprintf("Email: %s", config.EmailAddress) p.emailDisplay, err = NewStringItem(emailText, font, colors.White) if err != nil { return fmt.Errorf("unable to create email display texture: %w", err) @@ -106,8 +112,8 @@ func (p *Home) Init(ctx *PageCtx) error { } // Create license key display if exists - if p.Context.CfgPtr.LicenseKey != "" { - licenseKeyText := fmt.Sprintf("License Key: %s", p.Context.CfgPtr.LicenseKey) + if config.LicenseKey != "" { + licenseKeyText := fmt.Sprintf("License Key: %s", config.LicenseKey) p.licenseKeyDisplay, err = NewStringItem(licenseKeyText, font, colors.White) if err != nil { return fmt.Errorf("unable to create license key display texture: %w", err) @@ -116,7 +122,7 @@ func (p *Home) Init(ctx *PageCtx) error { } // Get base font size from database - baseFontSize := p.Context.CfgPtr.StandardFontSize + baseFontSize := config.StandardFontSize p.baseFontSize = baseFontSize // Scale the note text diff --git a/internal/page/licenseKeyPage.go b/internal/page/licenseKeyPage.go index d971d47..675354e 100644 --- a/internal/page/licenseKeyPage.go +++ b/internal/page/licenseKeyPage.go @@ -10,6 +10,7 @@ import ( "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" + "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/logger" "rhemawavetech.com/rhemawave/internal/shaderManager" @@ -55,7 +56,7 @@ func (p *LicenseKeyPage) Init(ctx *PageCtx) error { p.title = "License Key" // Get application font from database - applicationFont := "Roboto-Regular" + applicationFont := "SpaceMonoNerdFont-Regular" fm := fontManager.Get() textShader, ok := shaderManager.Get().Get("text") @@ -77,7 +78,11 @@ func (p *LicenseKeyPage) Init(ctx *PageCtx) error { p.titleTextureHeight = titleHeight // Load existing license key from database - licenseKey := p.Context.CfgPtr.LicenseKey + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + licenseKey := config.LicenseKey if licenseKey != "" { p.inputText = licenseKey @@ -188,9 +193,12 @@ func (p *LicenseKeyPage) HandleEvent(event *sdl.Event) error { sdl.StopTextInput() // Save license key to database - p.Context.CfgPtr.LicenseKey = p.inputText - p.Context.DbPtr.Save(p.Context.CfgPtr) - p.Context.RefreshConfig() + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + config.LicenseKey = p.inputText + p.Context.DbPtr.Save(config) // Write license key to plain text file for the updater if homeDir, err := os.UserHomeDir(); err == nil { @@ -239,7 +247,7 @@ func (p *LicenseKeyPage) HandleEvent(event *sdl.Event) error { // Update updates animations and changing textures and other changes using `dt` which represents a time delta in float32. func (p *LicenseKeyPage) Update(dt float32) error { // Get application font from database - applicationFont := "Roboto-Regular" + applicationFont := "SpaceMonoNerdFont-Regular" fm := fontManager.Get() sm := shaderManager.Get() @@ -302,8 +310,12 @@ func (p *LicenseKeyPage) Update(dt float32) error { // Render performs page drawing logic. func (p *LicenseKeyPage) Render() error { + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } // Get base font size from database - baseFontSize := p.Context.CfgPtr.StandardFontSize + baseFontSize := config.StandardFontSize sm := shaderManager.Get() diff --git a/internal/page/logViewerPage.go b/internal/page/logViewerPage.go index 0bf75ba..4f367ac 100644 --- a/internal/page/logViewerPage.go +++ b/internal/page/logViewerPage.go @@ -4,10 +4,11 @@ import ( "fmt" "strings" "time" - "slices" + "github.com/go-gl/gl/v3.3-core/gl" "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" + "rhemawavetech.com/rhemawave/internal/colors" "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/logger" @@ -25,6 +26,7 @@ type LogViewerPage struct { lineTextureIDs []uint32 lineTextureWidths []int32 lineTextureHeights []int32 + lineColors []sdl.Color hintTextureID uint32 hintTextureWidth int32 @@ -47,24 +49,37 @@ func (p *LogViewerPage) Init(ctx *PageCtx) error { return fmt.Errorf("%s", result.Error) } - // Format and word-wrap each log entry + // // Format and word-wrap each log entry // for _, entry := range logs { // formatted := fmt.Sprintf("[%s] [%s] %s", entry.Timestamp, entry.Level, entry.Message) // wrapped := wrapText(formatted, 100) // p.lines = append(p.lines, strings.Split(wrapped, "\n")...) // } - displayLevels := []string{"WARNING", "ERROR", "FATAL"} - - for _, entry := range logs { - if slices.Contains(displayLevels, entry.Level) { - logTime := time.UnixMilli(entry.Timestamp) - timeStr := logTime.Format("2006-01-02 15:04") - line := fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Message) - p.lines = append(p.lines, line) - } + + levelColors := map[string]sdl.Color{ + "DEBUG": colors.SkyBlue, + "INFO": colors.White, + "WARNING": colors.Yellow, + "ERROR": colors.RedOrange, } - applicationFont := "Roboto-Regular" + fallbackColor := colors.White + + p.lineColors = make([]sdl.Color, len(p.lines)) + + for _, entry := range logs { + color, ok := levelColors[entry.Level] + if !ok { + color = fallbackColor + } + logTime := time.UnixMilli(entry.Timestamp) + timeStr := logTime.Format("2006-01-02 15:04") + line := fmt.Sprintf("[%s] [%s] %s", timeStr, entry.Level, entry.Message) + p.lines = append(p.lines, line) + p.lineColors = append(p.lineColors, color) + } + + applicationFont := "SpaceMonoNerdFont-Regular" fm := fontManager.Get() textShader, ok := shaderManager.Get().Get("text") @@ -162,14 +177,15 @@ func (p *LogViewerPage) Update(dt float32) error { } func (p *LogViewerPage) Render() error { - baseFontSize := p.Context.CfgPtr.StandardFontSize + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + baseFontSize := config.StandardFontSize sm := shaderManager.Get() textShader, _ := sm.Get("text") - white := sdl.Color{R: 255, G: 255, B: 255, A: 255} - grey := sdl.Color{R: 180, G: 180, B: 180, A: 255} - titleFontSize := int32(48) titleScale := float32(titleFontSize) / float32(baseFontSize) contentFontSize := int32(24) @@ -189,14 +205,14 @@ func (p *LogViewerPage) Render() error { titleW := float32(p.titleTextureWidth) * titleScale titleX := p.Base.ScreenCenterX - int32(titleW/2) titleY := p.Base.ScreenHeight - margin - int32(titleH) - p.Base.RenderTexture(textShader, p.titleTextureID, mgl32.Vec2{float32(titleX), float32(titleY)}, mgl32.Vec2{titleW, titleH}, white) + p.Base.RenderTexture(textShader, p.titleTextureID, mgl32.Vec2{float32(titleX), float32(titleY)}, mgl32.Vec2{titleW, titleH}, colors.White) // Hint at bottom hintH := float32(p.hintTextureHeight) * hintScale hintW := float32(p.hintTextureWidth) * hintScale hintX := p.Base.ScreenCenterX - int32(hintW/2) hintY := margin - p.Base.RenderTexture(textShader, p.hintTextureID, mgl32.Vec2{float32(hintX), float32(hintY)}, mgl32.Vec2{hintW, hintH}, grey) + p.Base.RenderTexture(textShader, p.hintTextureID, mgl32.Vec2{float32(hintX), float32(hintY)}, mgl32.Vec2{hintW, hintH}, colors.Gray) // Content area bounds contentTop := titleY - margin @@ -232,7 +248,12 @@ func (p *LogViewerPage) Render() error { lineW := float32(p.lineTextureWidths[i]) * contentScale lineH := float32(p.lineTextureHeights[i]) * contentScale - p.Base.RenderTexture(textShader, p.lineTextureIDs[i], mgl32.Vec2{float32(contentLeftX), float32(currentY)}, mgl32.Vec2{lineW, lineH}, white) + color := colors.White + if i < len(p.lineColors) { + color = p.lineColors[i] + } + + p.Base.RenderTexture(textShader, p.lineTextureIDs[i], mgl32.Vec2{float32(contentLeftX), float32(currentY)}, mgl32.Vec2{lineW, lineH}, color) currentY -= p.lineHeight } diff --git a/internal/page/page.go b/internal/page/page.go index b3c0e65..b3dfb81 100644 --- a/internal/page/page.go +++ b/internal/page/page.go @@ -7,6 +7,7 @@ import ( "github.com/go-gl/gl/v3.3-core/gl" "github.com/go-gl/mathgl/mgl32" "github.com/veandco/go-sdl2/sdl" + "rhemawavetech.com/rhemawave/internal/logger" "rhemawavetech.com/rhemawave/internal/shaderManager" ) @@ -184,3 +185,54 @@ func (p *Base) RenderSolidColorQuad(shader *shaderManager.Shader, position, size func (p *Base) HandleEvent(event sdl.Event) error { return nil } func (p *Base) Update(dt float32) error { return nil } func (p *Base) Render() error { return nil } + +// --- Helper Functions --- +// keycodeToChar converts an SDL keycode to a rune, respecting SHIFT state. +// Returns 0 for non-printable keys. +func keycodeToChar(sym sdl.Keycode, mod uint16) rune { + shifted := mod&sdl.KMOD_SHIFT != 0 + + // Letters + if sym >= sdl.K_a && sym <= sdl.K_z { + ch := rune(sym) + if shifted { + ch -= 'a' - 'A' + } + logger.Info("Wifi Password entered: %v", ch) + return ch + } + + // Digits and their shifted symbols + if sym >= sdl.K_0 && sym <= sdl.K_9 { + if shifted { + shiftDigits := []rune{')', '!', '@', '#', '$', '%', '^', '&', '*', '('} + return shiftDigits[sym-sdl.K_0] + } + return rune(sym) + } + + // Common punctuation / symbols + type charPair struct{ normal, shifted rune } + punctuation := map[sdl.Keycode]charPair{ + sdl.K_SPACE: {' ', ' '}, + sdl.K_MINUS: {'-', '_'}, + sdl.K_EQUALS: {'=', '+'}, + sdl.K_LEFTBRACKET: {'[', '{'}, + sdl.K_RIGHTBRACKET: {']', '}'}, + sdl.K_BACKSLASH: {'\\', '|'}, + sdl.K_SEMICOLON: {';', ':'}, + sdl.K_QUOTE: {'\'', '"'}, + sdl.K_BACKQUOTE: {'`', '~'}, + sdl.K_COMMA: {',', '<'}, + sdl.K_PERIOD: {'.', '>'}, + sdl.K_SLASH: {'/', '?'}, + } + if pair, ok := punctuation[sym]; ok { + if shifted { + return pair.shifted + } + return pair.normal + } + + return 0 +} diff --git a/internal/page/proclamationOptions.go b/internal/page/proclamationOptions.go index 941a6a8..c0ac305 100644 --- a/internal/page/proclamationOptions.go +++ b/internal/page/proclamationOptions.go @@ -105,7 +105,7 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error { sync.SyncFrequencies(ctx.DbPtr) fm := fontManager.Get() - font, _ := fm.GetFont("Roboto-Regular") + font, _ := fm.GetFont("SpaceMonoNerdFont-Regular") p.font = font sm := shaderManager.Get() @@ -114,9 +114,14 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error { p.Base.Init(ctx) - itemScale := float32(32) / float32(ctx.CfgPtr.StandardFontSize) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + + itemScale := float32(32) / float32(config.StandardFontSize) p.title, _ = NewStringItem("Proclamation Browser", p.font, colors.White) - p.title.Scale(float32(64) / float32(ctx.CfgPtr.StandardFontSize)) + p.title.Scale(float32(64) / float32(config.StandardFontSize)) p.prompt, _ = NewStringItem("Type to Search Space to Select Enter to Save Escape to Exit", p.font, colors.White) p.prompt.Scale(itemScale * 0.8) @@ -183,7 +188,11 @@ func (p *ProclamationOptions) createFlatItem(name, id string, isCat bool, depth if isCat && depth == 0 { text = "[+] " + name } - itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + itemScale := float32(32) / float32(config.StandardFontSize) lbl, _ := NewStringItem(text, p.font, colors.White) lbl.Scale(itemScale) return &FlatItem{ @@ -277,7 +286,12 @@ func (p *ProclamationOptions) toggleExpansion(index int) { pureName := item.Label.content[4:] gl.DeleteTextures(1, &item.Label.ID) - itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + + itemScale := float32(32) / float32(config.StandardFontSize) if item.Expanded { p.collapse(index) item.Label, _ = NewStringItem("[+] "+pureName, p.font, colors.White) @@ -401,7 +415,11 @@ func (p *ProclamationOptions) rebuildSearchLabel() { if p.searchQuery == "" { return } - itemScale := float32(32) / float32(p.Context.CfgPtr.StandardFontSize) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + itemScale := float32(32) / float32(config.StandardFontSize) p.searchInput, _ = NewStringItem("Search: "+p.searchQuery, p.font, colors.Yellow) p.searchInput.Scale(itemScale * 1.1) } diff --git a/internal/page/router.go b/internal/page/router.go index eb8dda8..75dd312 100644 --- a/internal/page/router.go +++ b/internal/page/router.go @@ -2,7 +2,6 @@ package page import ( "gorm.io/gorm" - "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/download" ) @@ -23,7 +22,6 @@ const ( ) type PageCtx struct { - CfgPtr *db.AppConfig DbPtr *gorm.DB W, H int32 MessageChannel chan download.DownloadStatus diff --git a/internal/page/scrollerPage.go b/internal/page/scrollerPage.go index 6ec7a9f..157ce5b 100644 --- a/internal/page/scrollerPage.go +++ b/internal/page/scrollerPage.go @@ -220,8 +220,11 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error { } // Get line pattern from database - var err error - linePatternName := p.Context.CfgPtr.LinePattern + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + linePatternName := config.LinePattern p.activePattern, err = linePattern.Get(linePatternName) if err != nil { @@ -241,7 +244,7 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error { p.colorPattern = colorPattern.NewColorPattern(baseColors) // Font setup - p.fontScale = float32(32) / float32(p.Context.CfgPtr.StandardFontSize) + p.fontScale = float32(32) / float32(config.StandardFontSize) nLines := int(float32(p.ScreenHeight) / 32.0) p.lines = NewLineDeque(nLines * 2) @@ -286,17 +289,16 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error { if !started { var selectedAudio db.AudioFile if err := p.Context.DbPtr.Where("Selected = ?", true).First(&selectedAudio).Error; err != nil { - logger.Error("error querying database for selected audio: %v", err) selectedAudio = db.AudioFile{ Name: "OriginalAudio", - Path: filepath.Join(p.Context.CfgPtr.AssetsDir, "audio", "OriginalAudio.wav"), + Path: filepath.Join(config.AssetsDir, "audio", "OriginalAudio.wav"), Selected: true, Order: 0, } } logger.Info("Playing %s", selectedAudio.Path) - if err := mixer.Play(selectedAudio.Path, true, p.Context.CfgPtr); err != nil { + if err := mixer.Play(selectedAudio.Path, true, config); err != nil { logger.Error("Mixer returned an error: %v", err) } } @@ -421,7 +423,11 @@ func (p *ScrollerPage) loadProclamations() error { // audioPathForFrequency builds the on-disk path for a solfeggio frequency's // audio file, e.g. 396 -> "/audio/396Hz.wav". func (p *ScrollerPage) audioPathForFrequency(freq int) string { - return filepath.Join(p.Context.CfgPtr.AssetsDir, "audio", fmt.Sprintf("%dHz.wav", freq)) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + return filepath.Join(config.AssetsDir, "audio", fmt.Sprintf("%dHz.wav", freq)) } // switchAudioForFrequency swaps the currently playing track to match freq. @@ -450,9 +456,12 @@ func (p *ScrollerPage) switchAudioForFrequency(freq int) bool { logger.Warning("No audio file for %dHz (%s), keeping current track", freq, path) return false } - - mixer.Stop(3000, p.Context.CfgPtr) - if err := mixer.Play(path, true, p.Context.CfgPtr); err != nil { + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + mixer.Stop(3000, config) + if err := mixer.Play(path, true, config); err != nil { logger.Error("Mixer returned an error: %v", err) return false } @@ -723,7 +732,12 @@ func (p *ScrollerPage) Destroy() error { return nil } - mixer.Stop(3000, p.Context.CfgPtr) + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + + mixer.Stop(3000, config) // Delete each cached word texture exactly once. for k, item := range p.wordTextureCache { diff --git a/internal/page/settingsPage.go b/internal/page/settingsPage.go index 23cee0a..93eb689 100644 --- a/internal/page/settingsPage.go +++ b/internal/page/settingsPage.go @@ -6,6 +6,7 @@ import ( "github.com/go-gl/gl/v3.3-core/gl" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" + "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/shaderManager" ) @@ -34,7 +35,7 @@ func (p *Settings) Init(ctx *PageCtx) error { // Get font fm := fontManager.Get() - font, ok := fm.GetFont("Roboto-Regular") + font, ok := fm.GetFont("SpaceMonoNerdFont-Regular") if !ok { return fmt.Errorf("failed to get font: %w", sdl.GetError()) } @@ -127,7 +128,11 @@ func (p *Settings) Init(ctx *PageCtx) error { // TODO: Add entry for "About" // Get base font size from database - baseFontSize := p.Context.CfgPtr.StandardFontSize + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + baseFontSize := config.StandardFontSize // Calculate scales titleScale := float32(64) / float32(baseFontSize) diff --git a/internal/page/wifiSetupPage.go b/internal/page/wifiSetupPage.go index ce5f13a..35f18cb 100644 --- a/internal/page/wifiSetupPage.go +++ b/internal/page/wifiSetupPage.go @@ -1,14 +1,14 @@ package page import ( + "context" "fmt" - "time" "github.com/go-gl/gl/v3.3-core/gl" "github.com/go-gl/mathgl/mgl32" - "github.com/godbus/dbus/v5" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" + "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/keybinds" "rhemawavetech.com/rhemawave/internal/logger" @@ -16,19 +16,31 @@ import ( "rhemawavetech.com/rhemawave/internal/shaderManager" ) -// accessPointUIItem holds both the network data and its rendered texture. -type accessPointUIItem struct { - AP network.AccessPoint +// ─── Types ──────────────────────────────────────────────────────────────────── + +type networkUIItem struct { + Net network.Network Item StringItem } -// WiFiSetupPage manages the discovery and connection to Wi-Fi networks. +type wifiStatus int + +const ( + wifiStatusIdle wifiStatus = iota + wifiStatusScanning + wifiStatusConnecting + wifiStatusConnected + wifiStatusError +) + +// ─── Page ───────────────────────────────────────────────────────────────────── + type WiFiSetupPage struct { Base - networkManager *network.Manager applicationFont *fontManager.FontEntry - // Page-specific UI elements + // UI elements + BaseFontSize int titleItem StringItem scanningStatusItem StringItem connectionStatusItem StringItem @@ -36,671 +48,480 @@ type WiFiSetupPage struct { passwordInputItem StringItem passwordErrorItem StringItem - // Network list and selection - accessPoints []accessPointUIItem + // Network list + networks []networkUIItem selectedIndex int - scrollOffset int - // State management - isScanning bool - isEnteringPassword bool - isConnecting bool - connectionError string - passwordInput string - selectedAP *network.AccessPoint - wifiDevice *network.Device - connectionStatus *network.ConnectionStatus - activeSSID string // Tracks the CONFIRMED active network - pendingSSID string // Tracks the network we are TRYING to connect to - connectionAttemptTime time.Time - connectionTimeout time.Duration + // State + status wifiStatus + statusMessage string + connectError string - // Text input deduplication - textInputSupported bool + // Password entry + isEnteringPassword bool + passwordInput string + selectedNet *network.Network - // Async management - resultsChan chan []network.AccessPoint - statusChan chan *network.ConnectionStatus - errorChan chan error - stopScan chan struct{} + // Async + ctx context.Context + cancel context.CancelFunc + networksCh <-chan []network.Network + connectResultCh chan error } -// Init sets up the page, initializes the network manager, and starts a scan. -func (p *WiFiSetupPage) Init(ctx *PageCtx) error { +// ─── Init ───────────────────────────────────────────────────────────────────── +func (p *WiFiSetupPage) Init(ctx *PageCtx) error { if err := p.Base.Init(ctx); err != nil { return fmt.Errorf("failed base page initialization: %w", err) } - // Get application font from database - applicationFontName := "Roboto-Regular" - fm := fontManager.Get() - font, ok := fm.GetFont(applicationFontName) + font, ok := fm.GetFont("SpaceMonoNerdFont-Regular") if !ok { - return fmt.Errorf("could not find application font: %s", applicationFontName) + return fmt.Errorf("could not find application font: SpaceMonoNerdFont-Regular") } p.applicationFont = font - // Initialize network manager - nm, err := network.New() - if err != nil { - return fmt.Errorf("failed to initialize network manager: %w", err) - } - p.networkManager = nm + var err error - // Find Wi-Fi device - if err := p.networkManager.FindDevices(); err != nil { - // Clean up before returning error - p.networkManager.Close() - p.networkManager = nil - return fmt.Errorf("failed to find network devices: %w. Try rebooting the computer. If this is your 3rd reboot, call for help", err) - } - - // FindDevices() rebuilds m.Devices each call, so store a VALUE copy, - // not a pointer into the slice — it would be invalidated on next call. - for i := range p.networkManager.Devices { - if p.networkManager.Devices[i].Type == network.TypeWifi { - device := p.networkManager.Devices[i] - p.wifiDevice = &device - break - } - } - if p.wifiDevice == nil { - p.networkManager.Close() - p.networkManager = nil - return fmt.Errorf("no Wi-Fi adapter found. Try rebooting the computer. If this is your 3rd reboot, call for help") - } - - // Create UI elements - white := colors.White - p.titleItem, err = NewStringItem("Wi-Fi Setup", p.applicationFont, white) + p.titleItem, err = NewStringItem("Wi-Fi Setup", p.applicationFont, colors.White) if err != nil { return fmt.Errorf("failed to create title item: %w", err) } - p.scanningStatusItem, err = NewStringItem("Scanning for networks...", p.applicationFont, white) + p.scanningStatusItem, err = NewStringItem("Scanning for networks...", p.applicationFont, colors.White) if err != nil { return fmt.Errorf("failed to create scanning status item: %w", err) } - // Initialize channels and timeout - p.resultsChan = make(chan []network.AccessPoint) - p.statusChan = make(chan *network.ConnectionStatus, 1) - p.errorChan = make(chan error) - p.stopScan = make(chan struct{}) - p.connectionTimeout = 30 * time.Second + config, err := db.GetConfig(p.Context.DbPtr) + if err != nil { + panic(err) + } + p.BaseFontSize = config.StandardFontSize + + p.connectResultCh = make(chan error, 1) + p.ctx, p.cancel = context.WithCancel(context.Background()) - // Start scanning and status monitoring p.startScan() return nil } -// checkConnectionStatusLoop periodically checks the network status. -func (p *WiFiSetupPage) checkConnectionStatusLoop() { - ticker := time.NewTicker(2 * time.Second) // Check more frequently for better UX - defer ticker.Stop() +// ─── Scan ───────────────────────────────────────────────────────────────────── - status, _ := p.networkManager.CheckInternetConnection() - p.statusChan <- status - - for { - select { - case <-ticker.C: - status, _ := p.networkManager.CheckInternetConnection() - p.statusChan <- status - case <-p.stopScan: - return - } - } -} - -// startScan triggers a new asynchronous network scan. func (p *WiFiSetupPage) startScan() { - if p.stopScan != nil { - close(p.stopScan) - } - p.stopScan = make(chan struct{}) - - p.isScanning = true + p.status = wifiStatusScanning + p.statusMessage = "Scanning for networks..." p.selectedIndex = 0 - p.scrollOffset = 0 - p.accessPoints = nil + p.networks = nil - if p.wifiDevice != nil { - go p.networkManager.StartScan(p.resultsChan, p.errorChan, p.stopScan) - go p.checkConnectionStatusLoop() - } else { - p.isScanning = false + var err error + p.networksCh, err = network.ScanForNetworks(p.ctx) + if err != nil { + logger.Error("wifi: failed to start scan: %v", err) + p.status = wifiStatusError + p.statusMessage = "Failed to start network scan. No Wi-Fi adapter found." } } -// HandleEvent processes user input. +// ─── Input ──────────────────────────────────────────────────────────────────── + func (p *WiFiSetupPage) HandleEvent(event *sdl.Event) error { switch e := (*event).(type) { + case *sdl.TextInputEvent: + // SDL fires TextInputEvent for every printable character typed. + // This is the correct SDL2 way — no manual keycode mapping needed. if p.isEnteringPassword { - p.passwordInput += e.GetText() // Always append text - p.textInputSupported = true // Mark as supported - p.updatePasswordTexture() + p.passwordInput += e.GetText() + p.rebuildPasswordTexture() } case *sdl.KeyboardEvent: if e.Type != sdl.KEYDOWN { return nil } - if p.isEnteringPassword { - p.handlePasswordInput(e.Keysym.Sym, e.Keysym.Mod) + p.handlePasswordKey(e.Keysym.Sym) } else { - p.handleNetworkSelection(e.Keysym.Sym) + p.handleNavKey(e.Keysym.Sym) } } return nil } -// handlePasswordInput manages keyboard events during password entry. -// Update the signature to include mod -// handlePasswordInput manages keyboard events during password entry. -func (p *WiFiSetupPage) handlePasswordInput(sym sdl.Keycode, mod uint16) { +func (p *WiFiSetupPage) handlePasswordKey(sym sdl.Keycode) { switch sym { - case sdl.K_RETURN: - p.exitPasswordMode() - - p.pendingSSID = p.selectedAP.SSID - p.isConnecting = true - p.connectionError = "" - p.connectionAttemptTime = time.Now() - - err := p.networkManager.Connect(*p.wifiDevice, *p.selectedAP, p.passwordInput) - if err != nil { - p.isConnecting = false - p.pendingSSID = "" - p.connectionError = "Failed to initiate connection" - } - - p.isEnteringPassword = false + p.submitPassword() case sdl.K_BACKSPACE: if len(p.passwordInput) > 0 { - p.passwordInput = p.passwordInput[:len(p.passwordInput)-1] - logger.Info("WiFi Password backspace pressed") - p.updatePasswordTexture() + // Trim one rune safely + runes := []rune(p.passwordInput) + p.passwordInput = string(runes[:len(runes)-1]) + p.rebuildPasswordTexture() } case sdl.K_ESCAPE: - logger.Info("WiFi Password entry cancelled") - p.isEnteringPassword = false - p.pendingSSID = "" - p.connectionError = "" + logger.Info("wifi: password entry cancelled") p.exitPasswordMode() - - default: - // FALLBACK: If the kiosk environment doesn't fire TextInputEvents, - // manually convert keycodes to characters. - if !p.textInputSupported { - if ch := keycodeToChar(sym, mod); ch != 0 { - p.passwordInput += string(ch) - logger.Info("Manual character fallback: %c", ch) - p.updatePasswordTexture() - } - } + p.connectError = "" + p.selectedNet = nil } } -// enterPasswordMode disables global keybinds and starts SDL text input. -func (p *WiFiSetupPage) enterPasswordMode() { - keybinds.Enabled = false - - p.passwordInput = "" - - logger.Info("WiFi Password entry started") - - sdl.StartTextInput() -} - -// exitPasswordMode re-enables global keybinds and stops SDL text input. -func (p *WiFiSetupPage) exitPasswordMode() { - logger.Info("WiFi Password entry finished") - - keybinds.Enabled = true - sdl.StopTextInput() -} - -// keycodeToChar converts an SDL keycode to a rune, respecting SHIFT state. -// Returns 0 for non-printable keys. -func keycodeToChar(sym sdl.Keycode, mod uint16) rune { - shifted := mod&sdl.KMOD_SHIFT != 0 - - // Letters - if sym >= sdl.K_a && sym <= sdl.K_z { - ch := rune(sym) - if shifted { - ch -= 'a' - 'A' - } - logger.Info("Wifi Password entered: %v", ch) - return ch - } - - // Digits and their shifted symbols - if sym >= sdl.K_0 && sym <= sdl.K_9 { - if shifted { - shiftDigits := []rune{')', '!', '@', '#', '$', '%', '^', '&', '*', '('} - return shiftDigits[sym-sdl.K_0] - } - return rune(sym) - } - - // Common punctuation / symbols - type charPair struct{ normal, shifted rune } - punctuation := map[sdl.Keycode]charPair{ - sdl.K_SPACE: {' ', ' '}, - sdl.K_MINUS: {'-', '_'}, - sdl.K_EQUALS: {'=', '+'}, - sdl.K_LEFTBRACKET: {'[', '{'}, - sdl.K_RIGHTBRACKET: {']', '}'}, - sdl.K_BACKSLASH: {'\\', '|'}, - sdl.K_SEMICOLON: {';', ':'}, - sdl.K_QUOTE: {'\'', '"'}, - sdl.K_BACKQUOTE: {'`', '~'}, - sdl.K_COMMA: {',', '<'}, - sdl.K_PERIOD: {'.', '>'}, - sdl.K_SLASH: {'/', '?'}, - } - if pair, ok := punctuation[sym]; ok { - if shifted { - return pair.shifted - } - return pair.normal - } - - return 0 -} - -// handleNetworkSelection manages keyboard events for the network list. -func (p *WiFiSetupPage) handleNetworkSelection(sym sdl.Keycode) { +func (p *WiFiSetupPage) handleNavKey(sym sdl.Keycode) { switch sym { case sdl.K_UP: if p.selectedIndex > 0 { p.selectedIndex-- } + case sdl.K_DOWN: - if p.selectedIndex < len(p.accessPoints)-1 { + if p.selectedIndex < len(p.networks)-1 { p.selectedIndex++ } + case sdl.K_RETURN: - if len(p.accessPoints) > 0 && p.selectedIndex < len(p.accessPoints) { - p.selectedAP = &p.accessPoints[p.selectedIndex].AP - p.pendingSSID = p.selectedAP.SSID // Set for ALL networks (protected or not) - p.connectionError = "" - if p.selectedAP.IsProtected { - p.isEnteringPassword = true - p.passwordInput = "" - p.updatePasswordTexture() - p.updatePasswordPromptTexture() - p.enterPasswordMode() - } else { - p.isConnecting = true - p.connectionAttemptTime = time.Now() - err := p.networkManager.Connect(*p.wifiDevice, *p.selectedAP, "") - if err != nil { - p.isConnecting = false - p.pendingSSID = "" - p.connectionError = fmt.Sprintf("Failed to connect: %s", err.Error()) // Include actual error - } - } + if len(p.networks) == 0 || p.selectedIndex >= len(p.networks) { + return } + selected := p.networks[p.selectedIndex].Net + p.selectedNet = &selected + p.connectError = "" + + if selected.Security != network.SecurityOpen { + p.passwordInput = "" + p.enterPasswordMode() + } else { + p.connect("") + } + case sdl.K_r: - if !p.isScanning { + if p.status != wifiStatusScanning && p.status != wifiStatusConnecting { p.startScan() } + + case sdl.K_ESCAPE: + p.selectedNet = nil + p.connectError = "" } } -// Update checks for async results and updates UI state. +func (p *WiFiSetupPage) enterPasswordMode() { + keybinds.Enabled = false + p.isEnteringPassword = true + p.rebuildPasswordPromptTexture() + p.rebuildPasswordTexture() + sdl.StartTextInput() + logger.Info("wifi: password entry started for %q", p.selectedNet.SSID) +} + +func (p *WiFiSetupPage) exitPasswordMode() { + keybinds.Enabled = true + p.isEnteringPassword = false + sdl.StopTextInput() + logger.Info("wifi: password entry finished") +} + +func (p *WiFiSetupPage) submitPassword() { + p.exitPasswordMode() + p.connect(p.passwordInput) +} + +// ─── Connect ────────────────────────────────────────────────────────────────── + +func (p *WiFiSetupPage) connect(password string) { + if p.selectedNet == nil { + return + } + + ssid := p.selectedNet.SSID + p.status = wifiStatusConnecting + p.statusMessage = fmt.Sprintf("Connecting to \"%s\"...", ssid) + logger.Info("wifi: connecting to %q", ssid) + + // ConnectToNetwork blocks (up to 15s), so run it off the main goroutine. + go func() { + err := network.ConnectToNetwork(ssid, password) + p.connectResultCh <- err + }() +} + +// ─── Update ─────────────────────────────────────────────────────────────────── + func (p *WiFiSetupPage) Update(dt float32) error { select { - case results := <-p.resultsChan: - p.isScanning = false - p.buildNetworkUIList(results) - case status := <-p.statusChan: - p.connectionStatus = status - p.handleConnectionStatusUpdate(status) - p.updateConnectionStatusItem() - case err := <-p.errorChan: - p.isScanning = false - fmt.Printf("error scannign for networks %v", err) + + case nets, ok := <-p.networksCh: + if ok { + p.rebuildNetworkList(nets) + if p.status == wifiStatusScanning { + p.status = wifiStatusIdle + p.statusMessage = "" + } + } + + case err := <-p.connectResultCh: + if err != nil { + logger.Error("wifi: connection failed: %v", err) + p.status = wifiStatusError + p.connectError = fmt.Sprintf("Could not connect: %s", err.Error()) + p.statusMessage = "" + + // Drop back into password entry so the user can try again. + if p.selectedNet != nil && p.selectedNet.Security != network.SecurityOpen { + p.passwordInput = "" + p.rebuildPasswordErrorTexture() + p.enterPasswordMode() + } + } else { + ssid := "" + if p.selectedNet != nil { + ssid = p.selectedNet.SSID + } + logger.Info("wifi: connected to %q", ssid) + p.status = wifiStatusConnected + p.connectError = "" + p.statusMessage = fmt.Sprintf("Connected to \"%s\" — press F1 to continue", ssid) + // Trigger a fresh scan so the list shows the connected state. + p.startScan() + } + default: } - // Check for connection timeout - if p.isConnecting && time.Since(p.connectionAttemptTime) > p.connectionTimeout { - p.isConnecting = false - p.connectionError = "Connection timed out - Incorrect password?" - if p.selectedAP != nil && p.selectedAP.IsProtected { - p.isEnteringPassword = true - p.passwordInput = "" - p.updatePasswordTexture() - p.updatePasswordPromptTexture() - p.updatePasswordErrorTexture() - p.enterPasswordMode() - } - } + p.rebuildStatusTexture() return nil } -// handleConnectionStatusUpdate CHECKS0 if connection succeeded or failed -func (p *WiFiSetupPage) handleConnectionStatusUpdate(status *network.ConnectionStatus) { - if !p.isConnecting || p.pendingSSID == "" { - return - } +// ─── Texture builders ───────────────────────────────────────────────────────── - // Only consider it successful if we're connected to the EXACT network we tried to join - isConnectedToPending := status.StatusCode == network.StatusWifiConnectedInternetUp || - status.StatusCode == network.StatusWifiConnectedNoInternet - - if isConnectedToPending { - activeSSID := p.getActiveSSID() - if activeSSID == p.pendingSSID { // ONLY accept if it's the network we tried - logger.Info("UI synced: Connected to %s", activeSSID) - p.isConnecting = false - p.pendingSSID = "" - p.connectionError = "" - p.refreshNetworkColors() - return +func (p *WiFiSetupPage) rebuildNetworkList(nets []network.Network) { + for _, item := range p.networks { + if item.Item.ID != 0 { + gl.DeleteTextures(1, &item.Item.ID) } } - // Handle failure: If we've been trying for too long, show error - if status.StatusCode == network.StatusWifiAvailableNotConnected { - if time.Since(p.connectionAttemptTime) > 20*time.Second { - p.isConnecting = false - p.connectionError = "Connection failed - Check password or signal" - if p.selectedAP != nil && p.selectedAP.IsProtected { - p.isEnteringPassword = true - p.enterPasswordMode() - p.updatePasswordErrorTexture() + p.networks = make([]networkUIItem, 0, len(nets)) + + for _, n := range nets { + label := n.SSID + switch { + case n.Connected: + label += " ✓" + case n.Saved: + label += " ★" + } + if n.Security != network.SecurityOpen { + var secStr string + switch n.Security { + case network.SecurityWEP: + secStr = "WEP" + case network.SecurityWPA: + secStr = "WPA" + case network.SecurityWPA2: + secStr = "WPA2" + case network.SecurityWPA3: + secStr = "WPA3" + default: + secStr = "Secured" } - } - } -} - -// getAiveSSID queries NetworkManager for the currently active WiFi SSID -func (p *WiFiSetupPage) getActiveSSID() string { - if p.networkManager == nil || p.wifiDevice == nil { - return "" - } - - conn := p.networkManager.Conn() - - devObj := conn.Object("org.freedesktop.NetworkManager", p.wifiDevice.Path) - activeApProp, err := devObj.GetProperty("org.freedesktop.NetworkManager.Device.Wireless.ActiveAccessPoint") - if err != nil { - return "" - } - - activeApPath, ok := activeApProp.Value().(dbus.ObjectPath) - if !ok || activeApPath == "/" || activeApPath == "" { - return "" - } - - apObj := conn.Object("org.freedesktop.NetworkManager", activeApPath) - ssidProp, err := apObj.GetProperty("org.freedesktop.NetworkManager.AccessPoint.Ssid") - if err != nil { - return "" - } - - ssidBytes, ok := ssidProp.Value().([]byte) - if !ok { - return "" - } - - logger.Info("Active SSID: %s", string(ssidBytes)) - - return string(ssidBytes) -} - -// refreshNetworkColors updates the colors of network items based on active status -func (p *WiFiSetupPage) refreshNetworkColors() { - activeSSID := p.getActiveSSID() - p.activeSSID = activeSSID - - for i := range p.accessPoints { - if p.accessPoints[i].AP.SSID == activeSSID { - p.accessPoints[i].Item.Color = colors.LawnGreen - } else { - p.accessPoints[i].Item.Color = colors.White - } - } -} - -// updateConnectionStatusItem creates the colored status message item. -func (p *WiFiSetupPage) updateConnectionStatusItem() { - if p.connectionStatusItem.ID != 0 { - gl.DeleteTextures(1, &p.connectionStatusItem.ID) - } - - // Show connecting message if in progress - if p.isConnecting { - message := fmt.Sprintf("Connecting to %s...", p.pendingSSID) - item, err := NewStringItem(message, p.applicationFont, colors.Yellow) - if err == nil { - p.connectionStatusItem = item - } - return - } - - // Show connection error if present - if p.connectionError != "" { - item, err := NewStringItem(p.connectionError, p.applicationFont, colors.Red) - if err == nil { - p.connectionStatusItem = item - } - return - } - - if p.connectionStatus == nil { - return - } - - switch p.connectionStatus.StatusCode { - case network.StatusWifiConnectedInternetUp: - message := fmt.Sprintf("Connected to %s - Internet accessible | F1 to exit", p.activeSSID) - item, err := NewStringItem(message, p.applicationFont, colors.LawnGreen) - if err == nil { - p.connectionStatusItem = item - } - p.refreshNetworkColors() - - case network.StatusWifiAvailableNotConnected: - message := "WiFi available - Not connected | Select network or press R to rescan" - item, err := NewStringItem(message, p.applicationFont, colors.Yellow) - if err == nil { - p.connectionStatusItem = item + label += " [" + secStr + "]" } - case network.StatusEthernetConnectedInternetUp: - message := "Ethernet connected - Internet accessible | F1 to exit" - item, err := NewStringItem(message, p.applicationFont, colors.LawnGreen) - if err == nil { - p.connectionStatusItem = item + c := colors.White + if n.Connected { + c = colors.LawnGreen } - case network.StatusEthernetNotConnected: - message := "No network connection | Select WiFi network or press R to rescan" - item, err := NewStringItem(message, p.applicationFont, colors.Red) - if err == nil { - p.connectionStatusItem = item - } - - case network.StatusNoDevicesFound: - message := "No network devices found" - item, err := NewStringItem(message, p.applicationFont, colors.Red) - if err == nil { - p.connectionStatusItem = item - } - - case network.StatusError: - message := "Network status check failed" - item, err := NewStringItem(message, p.applicationFont, colors.Red) - if err == nil { - p.connectionStatusItem = item - } - - default: - item, err := NewStringItem(p.connectionStatus.Message, p.applicationFont, colors.White) - if err == nil { - p.connectionStatusItem = item - } - } -} - -// buildNetworkUIList creates the renderable textures for the list of discovered networks. -func (p *WiFiSetupPage) buildNetworkUIList(aps []network.AccessPoint) { - // Delete old textures to prevent memory leaks - for _, apItem := range p.accessPoints { - if apItem.Item.ID != 0 { - gl.DeleteTextures(1, &apItem.Item.ID) - } - } - - // Get the currently active Wi-Fi SSID - activeSSID := p.getActiveSSID() - p.activeSSID = activeSSID - - // Set IsActive flag based on the actual active SSID - for i := range aps { - aps[i].IsActive = (aps[i].SSID == p.activeSSID) - } - - p.accessPoints = make([]accessPointUIItem, len(aps)) - white := sdl.Color{R: 255, G: 255, B: 255, A: 255} - - for i, ap := range aps { - ssid := ap.SSID - if ap.IsProtected { - ssid += " [L]" - } - color := white - if ap.IsActive { - color = colors.LawnGreen - } - item, err := NewStringItem(ssid, p.applicationFont, color) + item, err := NewStringItem(label, p.applicationFont, c) if err != nil { + logger.Warning("wifi: failed to create item for %q: %v", n.SSID, err) continue } - p.accessPoints[i] = accessPointUIItem{AP: ap, Item: item} + p.networks = append(p.networks, networkUIItem{Net: n, Item: item}) } } -// updatePasswordTexture regenerates the texture for the password input field. -func (p *WiFiSetupPage) updatePasswordTexture() { +func (p *WiFiSetupPage) rebuildStatusTexture() { + if p.connectionStatusItem.ID != 0 { + gl.DeleteTextures(1, &p.connectionStatusItem.ID) + p.connectionStatusItem.ID = 0 + } + + var msg string + var c sdl.Color + + switch p.status { + case wifiStatusScanning: + msg = "Scanning for nearby networks, please wait..." + c = colors.White + case wifiStatusConnecting: + msg = p.statusMessage + c = colors.Yellow + case wifiStatusConnected: + msg = p.statusMessage + c = colors.LawnGreen + case wifiStatusError: + msg = p.connectError + if msg == "" { + msg = "Something went wrong. Press R to scan again." + } + c = colors.Red + default: + if len(p.networks) == 0 { + msg = "No networks found. Press R to scan again." + c = colors.Yellow + } else { + msg = "Select a network to connect — press R to rescan" + c = colors.White + } + } + + if msg == "" { + return + } + + item, err := NewStringItem(msg, p.applicationFont, c) + if err == nil { + p.connectionStatusItem = item + } +} + +func (p *WiFiSetupPage) rebuildPasswordTexture() { if p.passwordInputItem.ID != 0 { gl.DeleteTextures(1, &p.passwordInputItem.ID) } - maskedPassword := p.passwordInput - if maskedPassword == "" { - maskedPassword = " " + text := p.passwordInput + if text == "" { + text = " " // prevent empty texture } - item, err := NewStringItem(maskedPassword, p.applicationFont, sdl.Color{R: 255, G: 255, B: 255, A: 255}) + item, err := NewStringItem(text, p.applicationFont, colors.White) if err == nil { p.passwordInputItem = item } } -// updatePasswordPromptTexture creates the texture for the password prompt label. -func (p *WiFiSetupPage) updatePasswordPromptTexture() { +func (p *WiFiSetupPage) rebuildPasswordPromptTexture() { if p.passwordPromptItem.ID != 0 { gl.DeleteTextures(1, &p.passwordPromptItem.ID) } - prompt := fmt.Sprintf("Password for %s:", p.selectedAP.SSID) - item, err := NewStringItem(prompt, p.applicationFont, sdl.Color{R: 255, G: 255, B: 255, A: 255}) + if p.selectedNet == nil { + return + } + prompt := fmt.Sprintf("Enter password for \"%s\":", p.selectedNet.SSID) + item, err := NewStringItem(prompt, p.applicationFont, colors.White) if err == nil { p.passwordPromptItem = item } } -// updatePasswordErrorTexture creates the texture for password error message. -func (p *WiFiSetupPage) updatePasswordErrorTexture() { +func (p *WiFiSetupPage) rebuildPasswordErrorTexture() { if p.passwordErrorItem.ID != 0 { gl.DeleteTextures(1, &p.passwordErrorItem.ID) + p.passwordErrorItem.ID = 0 } - if p.connectionError != "" { - item, err := NewStringItem(p.connectionError, p.applicationFont, colors.DarkRed) - if err == nil { - p.passwordErrorItem = item - } + if p.connectError == "" { + return + } + item, err := NewStringItem(p.connectError, p.applicationFont, colors.Red) + if err == nil { + p.passwordErrorItem = item } } -// Render draws the entire page. +// ─── Render ─────────────────────────────────────────────────────────────────── + func (p *WiFiSetupPage) Render() error { - // Get base font size from database - baseFontSize := p.Context.CfgPtr.StandardFontSize - - // Colors & Config - bgColor := sdl.Color{R: 0, G: 0, B: 0, A: 255} - selectionColor := sdl.Color{R: 68, G: 71, B: 90, A: 255} - white := sdl.Color{R: 255, G: 255, B: 255, A: 255} - verticalMargin := float32(20) - solidShader, _ := shaderManager.Get().Get("solid_color") textShader, _ := shaderManager.Get().Get("text") - // Background - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{0, 0}, mgl32.Vec2{float32(p.ScreenWidth), float32(p.ScreenHeight)}, bgColor) + bgColor := sdl.Color{R: 0, G: 0, B: 0, A: 255} + selColor := sdl.Color{R: 68, G: 71, B: 90, A: 255} + white := colors.White + vertMargin := float32(20) - // Title - titleScale := float32(48) / float32(baseFontSize) + // Background + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{0, 0}, + mgl32.Vec2{float32(p.ScreenWidth), float32(p.ScreenHeight)}, + bgColor, + ) + + // Title — 48pt + titleScale := float32(48) / float32(p.BaseFontSize) titleW := float32(p.titleItem.W) * titleScale titleH := float32(p.titleItem.H) * titleScale - titleX := float32(p.ScreenCenterX) - (titleW / 2) + titleX := float32(p.ScreenCenterX) - titleW/2 titleY := float32(p.ScreenHeight) - titleH - 40 - p.Base.RenderTexture(textShader, p.titleItem.ID, mgl32.Vec2{titleX, titleY}, mgl32.Vec2{titleW, titleH}, white) + p.Base.RenderTexture(textShader, p.titleItem.ID, + mgl32.Vec2{titleX, titleY}, + mgl32.Vec2{titleW, titleH}, + white, + ) - // Status message - statusY := titleY - titleH - verticalMargin - if p.isScanning { - statusScale := float32(24) / float32(baseFontSize) - statusW := float32(p.scanningStatusItem.W) * statusScale - statusH := float32(p.scanningStatusItem.H) * statusScale - statusX := float32(p.ScreenCenterX) - (statusW / 2) - p.Base.RenderTexture(textShader, p.scanningStatusItem.ID, mgl32.Vec2{statusX, statusY}, mgl32.Vec2{statusW, statusH}, white) + // Status message — 30pt (was 24pt, now 1.25x) + statusY := titleY - titleH - vertMargin + if p.status == wifiStatusScanning { + scale := float32(30) / float32(p.BaseFontSize) + w := float32(p.scanningStatusItem.W) * scale + h := float32(p.scanningStatusItem.H) * scale + x := float32(p.ScreenCenterX) - w/2 + p.Base.RenderTexture(textShader, p.scanningStatusItem.ID, + mgl32.Vec2{x, statusY}, + mgl32.Vec2{w, h}, + white, + ) } else if p.connectionStatusItem.ID != 0 { - statusScale := float32(24) / float32(baseFontSize) - statusW := float32(p.connectionStatusItem.W) * statusScale - statusH := float32(p.connectionStatusItem.H) * statusScale - statusX := float32(p.ScreenCenterX) - (statusW / 2) - p.Base.RenderTexture(textShader, p.connectionStatusItem.ID, mgl32.Vec2{statusX, statusY}, mgl32.Vec2{statusW, statusH}, p.connectionStatusItem.Color) + scale := float32(30) / float32(p.BaseFontSize) + w := float32(p.connectionStatusItem.W) * scale + h := float32(p.connectionStatusItem.H) * scale + x := float32(p.ScreenCenterX) - w/2 + p.Base.RenderTexture(textShader, p.connectionStatusItem.ID, + mgl32.Vec2{x, statusY}, + mgl32.Vec2{w, h}, + p.connectionStatusItem.Color, + ) } // Network list - listY := statusY - verticalMargin - if len(p.accessPoints) > 0 { - itemHeight := int32(40) - listPadding := int32(10) - for i, apItem := range p.accessPoints { - itemYpos := listY - float32(int32(i+1)*itemHeight) - itemXpos := float32(p.ScreenCenterX - 350) - itemW := float32(700) - if i == p.selectedIndex { - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{itemXpos, itemYpos}, mgl32.Vec2{itemW, float32(itemHeight)}, selectionColor) - } + listY := statusY - vertMargin + itemH := int32(40) + listPad := int32(10) + listW := float32(700) + listX := float32(p.ScreenCenterX) - listW/2 - textScale := float32(24) / float32(baseFontSize) - textW := float32(apItem.Item.W) * textScale - textH := float32(apItem.Item.H) * textScale - textY := itemYpos + (float32(itemHeight) / 2) - (textH / 2) - textX := itemXpos + float32(listPadding) - p.Base.RenderTexture(textShader, apItem.Item.ID, mgl32.Vec2{textX, textY}, mgl32.Vec2{textW, textH}, apItem.Item.Color) + for i, item := range p.networks { + rowY := listY - float32(int32(i+1)*itemH) + + if i == p.selectedIndex { + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{listX, rowY}, + mgl32.Vec2{listW, float32(itemH)}, + selColor, + ) } + + scale := float32(24) / float32(p.BaseFontSize) + tw := float32(item.Item.W) * scale + th := float32(item.Item.H) * scale + tx := listX + float32(listPad) + ty := rowY + (float32(itemH)/2 - th/2) + p.Base.RenderTexture(textShader, item.Item.ID, + mgl32.Vec2{tx, ty}, + mgl32.Vec2{tw, th}, + item.Item.Color, + ) } - // Password dialog overlay + // Password dialog if p.isEnteringPassword { - if err := p.renderPasswordDialog(solidShader, textShader, float32(baseFontSize)); err != nil { + if err := p.renderPasswordDialog(solidShader, textShader, float32(p.BaseFontSize)); err != nil { return err } } @@ -708,106 +529,132 @@ func (p *WiFiSetupPage) Render() error { return nil } -// renderPasswordDialog draws the password entry modal. func (p *WiFiSetupPage) renderPasswordDialog(solidShader, textShader *shaderManager.Shader, baseFontSize float32) error { - overlayColor := sdl.Color{R: 0, G: 0, B: 0, A: 150} + overlayColor := sdl.Color{R: 0, G: 0, B: 0, A: 180} dialogBgColor := sdl.Color{R: 40, G: 42, B: 54, A: 255} boxBorderColor := sdl.Color{R: 120, G: 120, B: 120, A: 255} boxBgColor := sdl.Color{R: 30, G: 30, B: 30, A: 255} - white := sdl.Color{R: 255, G: 255, B: 255, A: 255} + white := colors.White - dialogW, dialogH := int32(600), int32(250) - if p.connectionError != "" { - dialogH = int32(300) // Make dialog taller if there's an error + dialogW := int32(600) + dialogH := int32(250) + if p.connectError != "" { + dialogH = 310 } - dialogX, dialogY := p.ScreenCenterX-(dialogW/2), p.ScreenCenterY-(dialogH/2) + dialogX := p.ScreenCenterX - dialogW/2 + dialogY := p.ScreenCenterY - dialogH/2 - // Overlay and dialog background - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{0, 0}, mgl32.Vec2{float32(p.ScreenWidth), float32(p.ScreenHeight)}, overlayColor) - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{float32(dialogX), float32(dialogY)}, mgl32.Vec2{float32(dialogW), float32(dialogH)}, dialogBgColor) + // Overlay + dialog box + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{0, 0}, + mgl32.Vec2{float32(p.ScreenWidth), float32(p.ScreenHeight)}, + overlayColor, + ) + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{float32(dialogX), float32(dialogY)}, + mgl32.Vec2{float32(dialogW), float32(dialogH)}, + dialogBgColor, + ) currentY := float32(dialogY+dialogH) - 30 - // Password error (if exists) - shown at the top in red + // Error message if p.passwordErrorItem.ID != 0 { - errorScale := float32(20) / baseFontSize - errorW := float32(p.passwordErrorItem.W) * errorScale - errorH := float32(p.passwordErrorItem.H) * errorScale - errorX := float32(p.ScreenCenterX) - (errorW / 2) - currentY -= errorH - p.Base.RenderTexture(textShader, p.passwordErrorItem.ID, mgl32.Vec2{errorX, currentY}, mgl32.Vec2{errorW, errorH}, colors.DarkRed) + scale := float32(20) / baseFontSize + w := float32(p.passwordErrorItem.W) * scale + h := float32(p.passwordErrorItem.H) * scale + x := float32(p.ScreenCenterX) - w/2 + currentY -= h + p.Base.RenderTexture(textShader, p.passwordErrorItem.ID, + mgl32.Vec2{x, currentY}, + mgl32.Vec2{w, h}, + colors.Red, + ) currentY -= 20 } - // Password prompt + // Prompt if p.passwordPromptItem.ID != 0 { - promptScale := float32(24) / baseFontSize - promptW := float32(p.passwordPromptItem.W) * promptScale - promptH := float32(p.passwordPromptItem.H) * promptScale - promptX := float32(p.ScreenCenterX) - (promptW / 2) - currentY -= promptH - p.Base.RenderTexture(textShader, p.passwordPromptItem.ID, mgl32.Vec2{promptX, currentY}, mgl32.Vec2{promptW, promptH}, white) + scale := float32(24) / baseFontSize + w := float32(p.passwordPromptItem.W) * scale + h := float32(p.passwordPromptItem.H) * scale + x := float32(p.ScreenCenterX) - w/2 + currentY -= h + p.Base.RenderTexture(textShader, p.passwordPromptItem.ID, + mgl32.Vec2{x, currentY}, + mgl32.Vec2{w, h}, + white, + ) currentY -= 30 } // Input box - padding, border := int32(4), int32(3) + padding := int32(4) + border := int32(3) boxW := int32(500) - targetFontSize := int32(36) - boxH := targetFontSize + (padding * 2) - borderBoxW, borderBoxH := boxW+(border*2), boxH+(border*2) - borderBoxX := p.ScreenCenterX - (borderBoxW / 2) - borderBoxY := int32(currentY) - boxH - (padding * 2) - boxX, boxY := p.ScreenCenterX-(boxW/2), int32(currentY)-boxH-padding + fontSize := int32(36) + boxH := fontSize + padding*2 + bboxW := boxW + border*2 + bboxH := boxH + border*2 + bboxX := p.ScreenCenterX - bboxW/2 + bboxY := int32(currentY) - boxH - padding*2 + boxX := p.ScreenCenterX - boxW/2 + boxY := int32(currentY) - boxH - padding - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{float32(borderBoxX), float32(borderBoxY)}, mgl32.Vec2{float32(borderBoxW), float32(borderBoxH)}, boxBorderColor) - p.Base.RenderSolidColorQuad(solidShader, mgl32.Vec2{float32(boxX), float32(boxY)}, mgl32.Vec2{float32(boxW), float32(boxH)}, boxBgColor) + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{float32(bboxX), float32(bboxY)}, + mgl32.Vec2{float32(bboxW), float32(bboxH)}, + boxBorderColor, + ) + p.Base.RenderSolidColorQuad(solidShader, + mgl32.Vec2{float32(boxX), float32(boxY)}, + mgl32.Vec2{float32(boxW), float32(boxH)}, + boxBgColor, + ) - // Password input text + // Password text (plain, unmasked) if p.passwordInputItem.ID != 0 { - inputScale := float32(targetFontSize) / baseFontSize - inputW := float32(p.passwordInputItem.W) * inputScale - inputH := float32(p.passwordInputItem.H) * inputScale - inputX := float32(boxX + padding) - inputY := float32(boxY + padding) - p.Base.RenderTexture(textShader, p.passwordInputItem.ID, mgl32.Vec2{inputX, inputY}, mgl32.Vec2{inputW, inputH}, white) + scale := float32(fontSize) / baseFontSize + w := float32(p.passwordInputItem.W) * scale + h := float32(p.passwordInputItem.H) * scale + p.Base.RenderTexture(textShader, p.passwordInputItem.ID, + mgl32.Vec2{float32(boxX + padding), float32(boxY + padding)}, + mgl32.Vec2{w, h}, + white, + ) } return nil } -// Destroy cleans up all resources used by the page. +// ─── Destroy ────────────────────────────────────────────────────────────────── + func (p *WiFiSetupPage) Destroy() error { - // Re-enable global keybinds in case we're destroyed during password entry. keybinds.Enabled = true + sdl.StopTextInput() - if p.stopScan != nil { - close(p.stopScan) - p.stopScan = nil + // Cancel the scan context — stops ScanForNetworks goroutine. + if p.cancel != nil { + p.cancel() } - p.networkManager.Close() - - gl.DeleteTextures(1, &p.titleItem.ID) - gl.DeleteTextures(1, &p.scanningStatusItem.ID) - if p.connectionStatusItem.ID != 0 { - gl.DeleteTextures(1, &p.connectionStatusItem.ID) - } - if p.passwordPromptItem.ID != 0 { - gl.DeleteTextures(1, &p.passwordPromptItem.ID) - } - if p.passwordInputItem.ID != 0 { - gl.DeleteTextures(1, &p.passwordInputItem.ID) - } - if p.passwordErrorItem.ID != 0 { - gl.DeleteTextures(1, &p.passwordErrorItem.ID) - } - - for _, apItem := range p.accessPoints { - if apItem.Item.ID != 0 { - gl.DeleteTextures(1, &apItem.Item.ID) + deleteTexture := func(id *uint32) { + if *id != 0 { + gl.DeleteTextures(1, id) + *id = 0 } } + deleteTexture(&p.titleItem.ID) + deleteTexture(&p.scanningStatusItem.ID) + deleteTexture(&p.connectionStatusItem.ID) + deleteTexture(&p.passwordPromptItem.ID) + deleteTexture(&p.passwordInputItem.ID) + deleteTexture(&p.passwordErrorItem.ID) + + for _, item := range p.networks { + deleteTexture(&item.Item.ID) + } + return p.Base.Destroy() } diff --git a/share/rhemawave/fonts/SpaceMonoNerdFont-Regular.ttf b/share/rhemawave/fonts/SpaceMonoNerdFont-Regular.ttf new file mode 100644 index 0000000..de3d014 Binary files /dev/null and b/share/rhemawave/fonts/SpaceMonoNerdFont-Regular.ttf differ diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/.gitignore b/vendor/github.com/Wifx/gonetworkmanager/v2/.gitignore new file mode 100644 index 0000000..5118da7 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/.gitignore @@ -0,0 +1,23 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +.idea/ \ No newline at end of file diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/AccessPoint.go b/vendor/github.com/Wifx/gonetworkmanager/v2/AccessPoint.go new file mode 100644 index 0000000..2d04000 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/AccessPoint.go @@ -0,0 +1,179 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + AccessPointInterface = NetworkManagerInterface + ".AccessPoint" + + /* Properties */ + AccessPointPropertyFlags = AccessPointInterface + ".Flags" // readable u + AccessPointPropertyWpaFlags = AccessPointInterface + ".WpaFlags" // readable u + AccessPointPropertyRsnFlags = AccessPointInterface + ".RsnFlags" // readable u + AccessPointPropertySsid = AccessPointInterface + ".Ssid" // readable ay + AccessPointPropertyFrequency = AccessPointInterface + ".Frequency" // readable u + AccessPointPropertyHwAddress = AccessPointInterface + ".HwAddress" // readable s + AccessPointPropertyMode = AccessPointInterface + ".Mode" // readable u + AccessPointPropertyMaxBitrate = AccessPointInterface + ".MaxBitrate" // readable u + AccessPointPropertyStrength = AccessPointInterface + ".Strength" // readable y + AccessPointPropertyLastSeen = AccessPointInterface + ".LastSeen" // readable i +) + +type AccessPoint interface { + GetPath() dbus.ObjectPath + + // GetPropertyFlags gets flags describing the capabilities of the access point. + GetPropertyFlags() (uint32, error) + + // GetPropertyWPAFlags gets flags describing the access point's capabilities + // according to WPA (Wi-Fi Protected Access). + GetPropertyWPAFlags() (uint32, error) + + // GetPropertyRSNFlags gets flags describing the access point's capabilities + // according to the RSN (Robust Secure Network) protocol. + GetPropertyRSNFlags() (uint32, error) + + // GetPropertySSID returns the Service Set Identifier identifying the access point. + GetPropertySSID() (string, error) + + // GetPropertyFrequency gets the radio channel frequency in use by the access point, in MHz. + GetPropertyFrequency() (uint32, error) + + // GetPropertyHWAddress gets the hardware address (BSSID) of the access point. + GetPropertyHWAddress() (string, error) + + // GetPropertyMode describes the operating mode of the access point. + GetPropertyMode() (Nm80211Mode, error) + + // GetPropertyMaxBitrate gets the maximum bitrate this access point is capable of, in kilobits/second (Kb/s). + GetPropertyMaxBitrate() (uint32, error) + + // GetPropertyStrength gets the current signal quality of the access point, in percent. + GetPropertyStrength() (uint8, error) + + // GetPropertyLastSeen The timestamp (in CLOCK_BOOTTIME seconds) for the last time the access point was found in scan results. + // A value of -1 means the access point has never been found in scan results. + GetPropertyLastSeen() (int32, error) + + MarshalJSON() ([]byte, error) +} + +func NewAccessPoint(objectPath dbus.ObjectPath) (AccessPoint, error) { + var a accessPoint + return &a, a.init(NetworkManagerInterface, objectPath) +} + +type accessPoint struct { + dbusBase +} + +func (a *accessPoint) GetPath() dbus.ObjectPath { + return a.obj.Path() +} + +func (a *accessPoint) GetPropertyFlags() (uint32, error) { + return a.getUint32Property(AccessPointPropertyFlags) +} + +func (a *accessPoint) GetPropertyWPAFlags() (uint32, error) { + return a.getUint32Property(AccessPointPropertyWpaFlags) +} + +func (a *accessPoint) GetPropertyRSNFlags() (uint32, error) { + return a.getUint32Property(AccessPointPropertyRsnFlags) +} + +func (a *accessPoint) GetPropertySSID() (string, error) { + r, err := a.getSliceByteProperty(AccessPointPropertySsid) + if err != nil { + return "", err + } + return string(r), nil +} + +func (a *accessPoint) GetPropertyFrequency() (uint32, error) { + return a.getUint32Property(AccessPointPropertyFrequency) +} + +func (a *accessPoint) GetPropertyHWAddress() (string, error) { + return a.getStringProperty(AccessPointPropertyHwAddress) +} + +func (a *accessPoint) GetPropertyMode() (Nm80211Mode, error) { + r, err := a.getUint32Property(AccessPointPropertyMode) + if err != nil { + return Nm80211ModeUnknown, err + } + return Nm80211Mode(r), nil +} + +func (a *accessPoint) GetPropertyMaxBitrate() (uint32, error) { + return a.getUint32Property(AccessPointPropertyMaxBitrate) +} + +func (a *accessPoint) GetPropertyStrength() (uint8, error) { + return a.getUint8Property(AccessPointPropertyStrength) +} + +func (a *accessPoint) GetPropertyLastSeen() (int32, error) { + return a.getInt32Property(AccessPointPropertyLastSeen) +} + +func (a *accessPoint) MarshalJSON() ([]byte, error) { + Flags, err := a.GetPropertyFlags() + if err != nil { + return nil, err + } + WPAFlags, err := a.GetPropertyWPAFlags() + if err != nil { + return nil, err + } + RSNFlags, err := a.GetPropertyRSNFlags() + if err != nil { + return nil, err + } + SSID, err := a.GetPropertySSID() + if err != nil { + return nil, err + } + Frequency, err := a.GetPropertyFrequency() + if err != nil { + return nil, err + } + HWAddress, err := a.GetPropertyHWAddress() + if err != nil { + return nil, err + } + Mode, err := a.GetPropertyMode() + if err != nil { + return nil, err + } + MaxBitrate, err := a.GetPropertyMaxBitrate() + if err != nil { + return nil, err + } + Strength, err := a.GetPropertyStrength() + if err != nil { + return nil, err + } + LastSeen, err := a.GetPropertyLastSeen() + if err != nil { + return nil, err + } + + return json.Marshal(map[string]interface{}{ + "Flags": Flags, + "WPAFlags": WPAFlags, + "RSNFlags": RSNFlags, + "SSID": SSID, + "Frequency": Frequency, + "HWAddress": HWAddress, + "Mode": Mode.String(), + "MaxBitrate": MaxBitrate, + "Strength": Strength, + "LastSeen": LastSeen, + }) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/ActiveConnection.go b/vendor/github.com/Wifx/gonetworkmanager/v2/ActiveConnection.go new file mode 100644 index 0000000..7a9a6e3 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/ActiveConnection.go @@ -0,0 +1,274 @@ +package gonetworkmanager + +import ( + "fmt" + + "github.com/godbus/dbus/v5" +) + +const ( + ActiveConnectionInterface = NetworkManagerInterface + ".Connection.Active" + + /* Properties */ + ActiveConnectionPropertyConnection = ActiveConnectionInterface + ".Connection" // readable o + ActiveConnectionPropertySpecificObject = ActiveConnectionInterface + ".SpecificObject" // readable o + ActiveConnectionPropertyId = ActiveConnectionInterface + ".Id" // readable s + ActiveConnectionPropertyUuid = ActiveConnectionInterface + ".Uuid" // readable s + ActiveConnectionPropertyType = ActiveConnectionInterface + ".Type" // readable s + ActiveConnectionPropertyDevices = ActiveConnectionInterface + ".Devices" // readable ao + ActiveConnectionPropertyState = ActiveConnectionInterface + ".State" // readable u + ActiveConnectionPropertyStateFlags = ActiveConnectionInterface + ".StateFlags" // readable u + ActiveConnectionPropertyDefault = ActiveConnectionInterface + ".Default" // readable b + ActiveConnectionPropertyIp4Config = ActiveConnectionInterface + ".Ip4Config" // readable o + ActiveConnectionPropertyDhcp4Config = ActiveConnectionInterface + ".Dhcp4Config" // readable o + ActiveConnectionPropertyDefault6 = ActiveConnectionInterface + ".Default6" // readable b + ActiveConnectionPropertyIp6Config = ActiveConnectionInterface + ".Ip6Config" // readable o + ActiveConnectionPropertyDhcp6Config = ActiveConnectionInterface + ".Dhcp6Config" // readable o + ActiveConnectionPropertyVpn = ActiveConnectionInterface + ".Vpn" // readable b + ActiveConnectionPropertyMaster = ActiveConnectionInterface + ".Master" // readable o + + /* Signals */ + ActiveConnectionSignalStateChanged = "StateChanged" // u state, u reason + +) + +type ActiveConnection interface { + GetPath() dbus.ObjectPath + + // GetPropertyConnection gets connection object of the connection. + GetPropertyConnection() (Connection, error) + + // GetPropertySpecificObject gets a specific object associated with the active connection. + GetPropertySpecificObject() (AccessPoint, error) + + // GetPropertyID gets the ID of the connection. + GetPropertyID() (string, error) + + // GetPropertyUUID gets the UUID of the connection. + GetPropertyUUID() (string, error) + + // GetPropertyType gets the type of the connection. + GetPropertyType() (string, error) + + // GetPropertyDevices gets array of device objects which are part of this active connection. + GetPropertyDevices() ([]Device, error) + + // GetPropertyState gets the state of the connection. + GetPropertyState() (NmActiveConnectionState, error) + + // GetPropertyStateFlags gets the state flags of the connection. + GetPropertyStateFlags() (uint32, error) + + // GetPropertyDefault gets the default IPv4 flag of the connection. + GetPropertyDefault() (bool, error) + + // GetPropertyIP4Config gets the IP4Config of the connection. + GetPropertyIP4Config() (IP4Config, error) + + // GetPropertyDHCP4Config gets the DHCP6Config of the connection. + GetPropertyDHCP4Config() (DHCP4Config, error) + + // GetPropertyDefault6 gets the default IPv6 flag of the connection. + GetPropertyDefault6() (bool, error) + + // GetPropertyIP6Config gets the IP6Config of the connection. + GetPropertyIP6Config() (IP6Config, error) + + // GetPropertyDHCP6Config gets the DHCP4Config of the connection. + GetPropertyDHCP6Config() (DHCP6Config, error) + + // GetPropertyVPN gets the VPN flag of the connection. + GetPropertyVPN() (bool, error) + + // GetPropertyMaster gets the master device of the connection. + GetPropertyMaster() (Device, error) + + SubscribeState(receiver chan StateChange, exit chan struct{}) (err error) +} + +func NewActiveConnection(objectPath dbus.ObjectPath) (ActiveConnection, error) { + var a activeConnection + return &a, a.init(NetworkManagerInterface, objectPath) +} + +type activeConnection struct { + dbusBase +} + +func (a *activeConnection) GetPath() dbus.ObjectPath { + return a.obj.Path() +} + +func (a *activeConnection) GetPropertyConnection() (Connection, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyConnection) + if err != nil { + return nil, err + } + con, err := NewConnection(path) + if err != nil { + return nil, err + } + return con, nil +} + +func (a *activeConnection) GetPropertySpecificObject() (AccessPoint, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertySpecificObject) + if err != nil { + return nil, err + } + ap, err := NewAccessPoint(path) + if err != nil { + return nil, err + } + return ap, nil +} + +func (a *activeConnection) GetPropertyID() (string, error) { + return a.getStringProperty(ActiveConnectionPropertyId) +} + +func (a *activeConnection) GetPropertyUUID() (string, error) { + return a.getStringProperty(ActiveConnectionPropertyUuid) +} + +func (a *activeConnection) GetPropertyType() (string, error) { + return a.getStringProperty(ActiveConnectionPropertyType) +} + +func (a *activeConnection) GetPropertyDevices() ([]Device, error) { + paths, err := a.getSliceObjectProperty(ActiveConnectionPropertyDevices) + if err != nil { + return nil, err + } + devices := make([]Device, len(paths)) + for i, path := range paths { + devices[i], err = DeviceFactory(path) + if err != nil { + return nil, err + } + } + return devices, nil +} +func (a *activeConnection) GetPropertyState() (NmActiveConnectionState, error) { + v, err := a.getUint32Property(ActiveConnectionPropertyState) + return NmActiveConnectionState(v), err +} + +func (a *activeConnection) GetPropertyStateFlags() (uint32, error) { + return a.getUint32Property(ActiveConnectionPropertyStateFlags) +} + +func (a *activeConnection) GetPropertyDefault() (bool, error) { + b, err := a.getProperty(ActiveConnectionPropertyDefault) + if err != nil { + return false, err + } + return b.(bool), nil +} + +func (a *activeConnection) GetPropertyIP4Config() (IP4Config, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyIp4Config) + if err != nil || path == "/" { + return nil, err + } + return NewIP4Config(path) +} + +func (a *activeConnection) GetPropertyDHCP4Config() (DHCP4Config, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyDhcp4Config) + if err != nil || path == "/" { + return nil, err + } + return NewDHCP4Config(path) +} + +func (a *activeConnection) GetPropertyDefault6() (bool, error) { + return a.getBoolProperty(ActiveConnectionPropertyDefault6) +} + +func (a *activeConnection) GetPropertyIP6Config() (IP6Config, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyIp6Config) + if err != nil || path == "/" { + return nil, err + } + + return NewIP6Config(path) +} + +func (a *activeConnection) GetPropertyDHCP6Config() (DHCP6Config, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyDhcp6Config) + if err != nil || path == "/" { + return nil, err + } + + return NewDHCP6Config(path) +} + +func (a *activeConnection) GetPropertyVPN() (bool, error) { + ret, err := a.getProperty(ActiveConnectionPropertyVpn) + if err != nil { + return false, err + } + return ret.(bool), nil +} + +func (a *activeConnection) GetPropertyMaster() (Device, error) { + path, err := a.getObjectProperty(ActiveConnectionPropertyMaster) + if err != nil || path == "/" { + return nil, err + } + return DeviceFactory(path) +} + +type StateChange struct { + Path dbus.ObjectPath + State NmActiveConnectionState + Reason NmActiveConnectionStateReason +} + +func (a *activeConnection) SubscribeState(receiver chan StateChange, exit chan struct{}) (err error) { + + channel := make(chan *dbus.Signal, 1) + + a.conn.Signal(channel) + + err = a.conn.AddMatchSignal( + dbus.WithMatchInterface(ActiveConnectionInterface), + dbus.WithMatchMember(ActiveConnectionSignalStateChanged), + dbus.WithMatchObjectPath(a.GetPath()), + ) + if err != nil { + return err + } + + go func() { + for { + select { + case signal, ok := <-channel: + if !ok { + err = fmt.Errorf("connection closed for %s", ActiveConnectionSignalStateChanged) + return + } + + if signal.Name != ActiveConnectionInterface+"."+ActiveConnectionSignalStateChanged { + continue + } + + stateChange := StateChange{ + Path: signal.Path, + State: NmActiveConnectionState(signal.Body[0].(uint32)), + Reason: NmActiveConnectionStateReason(signal.Body[1].(uint32)), + } + + receiver <- stateChange + + case <-exit: + a.conn.RemoveSignal(channel) + close(channel) + return + } + } + }() + + return +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/CHANGELOG.md b/vendor/github.com/Wifx/gonetworkmanager/v2/CHANGELOG.md new file mode 100644 index 0000000..fa24062 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/CHANGELOG.md @@ -0,0 +1,85 @@ +# Changelog + +All notable changes to this project since will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.1.0] - 2023-01-19 + +### Added + +- Add device auto-connect setter + +### Fixed + +- Connection settings route and address data types + +## [2.0.0] - 2022-11-22 + +### Changes + +- Update go-dbus to v5.1.0 +- **BREAKING CHANGE** : Generic recursive settings map dbus variants decoding + +## [0.5.0] - 2022-11-22 + +### Added + +- Godoc standard comment prefix +- DnsManager +- Device: GetIp4Connectivity +- Constants for Nm80211APSec +- Add gitignore + +### Fixed + +- CheckpointCreate: fix devicePaths variable scope + +## [0.4.0] - 2022-01-17 + +### Added + +- AccessPoint: add LastSeen property + +### Changed + +- Examples: move examples to their own subfolders + +### Fixed + +- DeviceWireless: remove duplicated fields +- PrimaryConnection: use ActiveConnection type +- SubscribeState: add the path to the recieved chan type, catch connect event for ActiveConnection + +## [0.3.0] - 2020-03-26 + +### Added + +- SetPropertyManaged (@joseffilzmaier) +- GetConnectionByUUID (@paulburlumi) +- VpnConnection +- ActiveConnectionSignalStateChanged +- CheckpointRollback +- SetPropertyWirelessEnabled (@Raqbit) +- Settings.ReloadConnections (@appnostic-io) + +Static connection example (@everactivemilligan) + +### Fixed + +- GetPropertyRouteData panic (@zhengdelun) + +## [0.2.0] - 2020-03-06 + +### Fixed + +- added missing flag for Reload +- added parameter specific_object for AddAndActivateConnection +- Fix CheckpointCreateand GetPropertyCheckpoints + +### Added + +- Add property setter helper +- Add Device.SetPropertyRefreshRateMs +- Add Device.Reapply \ No newline at end of file diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/Checkpoint.go b/vendor/github.com/Wifx/gonetworkmanager/v2/Checkpoint.go new file mode 100644 index 0000000..be60d27 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/Checkpoint.go @@ -0,0 +1,79 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + CheckpointInterface = NetworkManagerInterface + ".Checkpoint" + + /* Properties */ + CheckpointPropertyDevices = CheckpointInterface + ".Devices" // readable ao + CheckpointPropertyCreated = CheckpointInterface + ".Created" // readable x + CheckpointPropertyRollbackTimeout = CheckpointInterface + ".RollbackTimeout" // readable u +) + +type Checkpoint interface { + GetPath() dbus.ObjectPath + + // GetPropertyDevices Array of object paths for devices which are part of this checkpoint. + GetPropertyDevices() ([]Device, error) + + // GetPropertyCreated The timestamp (in CLOCK_BOOTTIME milliseconds) of checkpoint creation. + GetPropertyCreated() (int64, error) + + // GetPropertyRollbackTimeout Timeout in seconds for automatic rollback, or zero. + GetPropertyRollbackTimeout() (uint32, error) + + MarshalJSON() ([]byte, error) +} + +func NewCheckpoint(objectPath dbus.ObjectPath) (Checkpoint, error) { + var c checkpoint + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type checkpoint struct { + dbusBase +} + +func (c *checkpoint) GetPropertyDevices() ([]Device, error) { + devicesPaths, err := c.getSliceObjectProperty(CheckpointPropertyDevices) + if err != nil { + return nil, err + } + + devices := make([]Device, len(devicesPaths)) + for i, path := range devicesPaths { + devices[i], err = NewDevice(path) + if err != nil { + return devices, err + } + } + + return devices, nil +} + +func (c *checkpoint) GetPropertyCreated() (int64, error) { + return c.getInt64Property(CheckpointPropertyCreated) +} + +func (c *checkpoint) GetPropertyRollbackTimeout() (uint32, error) { + return c.getUint32Property(CheckpointPropertyRollbackTimeout) +} + +func (c *checkpoint) GetPath() dbus.ObjectPath { + return c.obj.Path() +} + +func (c *checkpoint) MarshalJSON() ([]byte, error) { + m := make(map[string]interface{}) + + m["Devices"], _ = c.GetPropertyDevices() + m["Created"], _ = c.GetPropertyCreated() + m["RollbackTimeout"], _ = c.GetPropertyRollbackTimeout() + + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/Connection.go b/vendor/github.com/Wifx/gonetworkmanager/v2/Connection.go new file mode 100644 index 0000000..8687703 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/Connection.go @@ -0,0 +1,184 @@ +package gonetworkmanager + +import ( + "encoding/json" + "github.com/godbus/dbus/v5" +) + +const ( + ConnectionInterface = SettingsInterface + ".Connection" + + /* Methods */ + ConnectionUpdate = ConnectionInterface + ".Update" + ConnectionUpdateUnsaved = ConnectionInterface + ".UpdateUnsaved" + ConnectionDelete = ConnectionInterface + ".Delete" + ConnectionGetSettings = ConnectionInterface + ".GetSettings" + ConnectionGetSecrets = ConnectionInterface + ".GetSecrets" + ConnectionClearSecrets = ConnectionInterface + ".ClearSecrets" + ConnectionSave = ConnectionInterface + ".Save" + ConnectionUpdate2 = ConnectionInterface + ".Update2" + + /* Properties */ + ConnectionPropertyUnsaved = ConnectionInterface + ".Unsaved" // readable b + ConnectionPropertyFlags = ConnectionInterface + ".Flags" // readable u + ConnectionPropertyFilename = ConnectionInterface + ".Filename" // readable s +) + +//type ConnectionSettings map[string]map[string]interface{} +type ConnectionSettings map[string]map[string]interface{} + +type Connection interface { + GetPath() dbus.ObjectPath + + // Update the connection with new settings and properties (replacing all previous settings and properties) and save the connection to disk. Secrets may be part of the update request, and will be either stored in persistent storage or sent to a Secret Agent for storage, depending on the flags associated with each secret. + Update(settings ConnectionSettings) error + + // UpdateUnsaved Update the connection with new settings and properties (replacing all previous settings and properties) but do not immediately save the connection to disk. Secrets may be part of the update request and may sent to a Secret Agent for storage, depending on the flags associated with each secret. Use the 'Save' method to save these changes to disk. Note that unsaved changes will be lost if the connection is reloaded from disk (either automatically on file change or due to an explicit ReloadConnections call). + UpdateUnsaved(settings ConnectionSettings) error + + // Delete the connection. + Delete() error + + // GetSettings gets the settings maps describing this network configuration. + // This will never include any secrets required for connection to the + // network, as those are often protected. Secrets must be requested + // separately using the GetSecrets() method. + GetSettings() (ConnectionSettings, error) + + // GetSecrets Get the secrets belonging to this network configuration. Only secrets from + // persistent storage or a Secret Agent running in the requestor's session + // will be returned. The user will never be prompted for secrets as a result + // of this request. + GetSecrets(settingName string) (ConnectionSettings, error) + + // ClearSecrets Clear the secrets belonging to this network connection profile. + ClearSecrets() error + + // Save a "dirty" connection (that had previously been updated with UpdateUnsaved) to persistent storage. + Save() error + + // GetPropertyUnsaved If set, indicates that the in-memory state of the connection does not match the on-disk state. This flag will be set when UpdateUnsaved() is called or when any connection details change, and cleared when the connection is saved to disk via Save() or from internal operations. + GetPropertyUnsaved() (bool, error) + + // GetPropertyFlags Additional flags of the connection profile. + GetPropertyFlags() (uint32, error) + + // GetPropertyFilename File that stores the connection in case the connection is file-backed. + GetPropertyFilename() (string, error) + + MarshalJSON() ([]byte, error) +} + +func NewConnection(objectPath dbus.ObjectPath) (Connection, error) { + var c connection + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type connection struct { + dbusBase +} + +func (c *connection) GetPath() dbus.ObjectPath { + return c.obj.Path() +} + +func (c *connection) Update(settings ConnectionSettings) error { + return c.call(ConnectionUpdate, settings) +} + +func (c *connection) UpdateUnsaved(settings ConnectionSettings) error { + return c.call(ConnectionUpdateUnsaved, settings) +} + +func (c *connection) Delete() error { + return c.call(ConnectionDelete) +} + +func (c *connection) GetSettings() (ConnectionSettings, error) { + var settings map[string]map[string]dbus.Variant + + if err := c.callWithReturn(&settings, ConnectionGetSettings); err != nil { + return nil, err + } + + return decodeSettings(settings), nil +} + +func (c *connection) GetSecrets(settingName string) (ConnectionSettings, error) { + var settings map[string]map[string]dbus.Variant + + if err := c.callWithReturn(&settings, ConnectionGetSecrets, settingName); err != nil { + return nil, err + } + + return decodeSettings(settings), nil +} + +func decodeSettings(input map[string]map[string]dbus.Variant) (settings ConnectionSettings) { + valueMap := ConnectionSettings{} + for key, data := range input { + valueMap[key] = decode(data).(map[string]interface{}) + } + return valueMap +} + +func decode(input interface{}) (value interface{}) { + if variant, isVariant := input.(dbus.Variant); isVariant { + return decode(variant.Value()) + } else if inputMap, isMap := input.(map[string]dbus.Variant); isMap { + return decodeMap(inputMap) + } else if inputArray, isArray := input.([]dbus.Variant); isArray { + return decodeArray(inputArray) + } else if inputArray, isArray := input.([]map[string]dbus.Variant); isArray { + return decodeMapArray(inputArray) + } else { + return input + } +} + +func decodeArray(input []dbus.Variant) (value []interface{}) { + for _, data := range input { + value = append(value, decode(data)) + } + return +} + +func decodeMapArray(input []map[string]dbus.Variant) (value []map[string]interface{}) { + for _, data := range input { + value = append(value, decodeMap(data)) + } + return +} + +func decodeMap(input map[string]dbus.Variant) (value map[string]interface{}) { + value = map[string]interface{}{} + for key, data := range input { + value[key] = decode(data) + } + return +} + +func (c *connection) ClearSecrets() error { + return c.call(ConnectionClearSecrets) +} + +func (c *connection) Save() error { + return c.call(ConnectionSave) +} + +func (c *connection) GetPropertyUnsaved() (bool, error) { + return c.getBoolProperty(ConnectionPropertyUnsaved) +} + +func (c *connection) GetPropertyFlags() (uint32, error) { + return c.getUint32Property(ConnectionPropertyFlags) +} + +func (c *connection) GetPropertyFilename() (string, error) { + return c.getStringProperty(ConnectionPropertyFilename) +} + +func (c *connection) MarshalJSON() ([]byte, error) { + s, _ := c.GetSettings() + return json.Marshal(s) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP4Config.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP4Config.go new file mode 100644 index 0000000..e849c01 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP4Config.go @@ -0,0 +1,56 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DHCP4ConfigInterface = NetworkManagerInterface + ".DHCP4Config" + + // Properties + DHCP4ConfigPropertyOptions = DHCP4ConfigInterface + ".Options" +) + +type DHCP4Options map[string]interface{} + +type DHCP4Config interface { + // GetPropertyOptions GetOptions gets options map of configuration returned by the IPv4 DHCP server. + GetPropertyOptions() (DHCP4Options, error) + + MarshalJSON() ([]byte, error) +} + +func NewDHCP4Config(objectPath dbus.ObjectPath) (DHCP4Config, error) { + var c dhcp4Config + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type dhcp4Config struct { + dbusBase +} + +func (c *dhcp4Config) GetPropertyOptions() (DHCP4Options, error) { + options, err := c.getMapStringVariantProperty(DHCP4ConfigPropertyOptions) + rv := make(DHCP4Options) + if err != nil { + return rv, err + } + + for k, v := range options { + rv[k] = v.Value() + } + + return rv, nil +} + +func (c *dhcp4Config) MarshalJSON() ([]byte, error) { + Options, err := c.GetPropertyOptions() + if err != nil { + return nil, err + } + return json.Marshal(map[string]interface{}{ + "Options": Options, + }) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP6Config.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP6Config.go new file mode 100644 index 0000000..6e40137 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DHCP6Config.go @@ -0,0 +1,54 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DHCP6ConfigInterface = NetworkManagerInterface + ".DHCP6Config" + + // Properties + DHCP6ConfigPropertyOptions = DHCP6ConfigInterface + ".Options" +) + +type DHCP6Options map[string]interface{} + +type DHCP6Config interface { + // GetPropertyOptions GetOptions gets options map of configuration returned by the IPv4 DHCP server. + GetPropertyOptions() (DHCP6Options, error) + + MarshalJSON() ([]byte, error) +} + +func NewDHCP6Config(objectPath dbus.ObjectPath) (DHCP6Config, error) { + var c dhcp6Config + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type dhcp6Config struct { + dbusBase +} + +func (c *dhcp6Config) GetPropertyOptions() (DHCP6Options, error) { + options, err := c.getMapStringVariantProperty(DHCP6ConfigPropertyOptions) + rv := make(DHCP6Options) + + if err != nil { + return rv, err + } + + for k, v := range options { + rv[k] = v.Value() + } + + return rv, nil +} + +func (c *dhcp6Config) MarshalJSON() ([]byte, error) { + m := make(map[string]interface{}) + m["Options"], _ = c.GetPropertyOptions() + + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/Device.go b/vendor/github.com/Wifx/gonetworkmanager/v2/Device.go new file mode 100644 index 0000000..1531cce --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/Device.go @@ -0,0 +1,434 @@ +package gonetworkmanager + +import ( + "encoding/json" + "fmt" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceInterface = NetworkManagerInterface + ".Device" + + /* Methods */ + DeviceReapply = DeviceInterface + ".Reapply" + DeviceGetAppliedConnection = DeviceInterface + ".GetAppliedConnection" + DeviceDisconnect = DeviceInterface + ".Disconnect" + DeviceDelete = DeviceInterface + ".Delete" + + /* Properties */ + DevicePropertyUdi = DeviceInterface + ".Udi" // readable s + DevicePropertyInterface = DeviceInterface + ".Interface" // readable s + DevicePropertyIpInterface = DeviceInterface + ".IpInterface" // readable s + DevicePropertyDriver = DeviceInterface + ".Driver" // readable s + DevicePropertyDriverVersion = DeviceInterface + ".DriverVersion" // readable s + DevicePropertyFirmwareVersion = DeviceInterface + ".FirmwareVersion" // readable s + DevicePropertyCapabilities = DeviceInterface + ".Capabilities" // readable u + DevicePropertyState = DeviceInterface + ".State" // readable u + DevicePropertyStateReason = DeviceInterface + ".StateReason" // readable (uu) + DevicePropertyActiveConnection = DeviceInterface + ".ActiveConnection" // readable o + DevicePropertyIp4Config = DeviceInterface + ".Ip4Config" // readable o + DevicePropertyDhcp4Config = DeviceInterface + ".Dhcp4Config" // readable o + DevicePropertyIp6Config = DeviceInterface + ".Ip6Config" // readable o + DevicePropertyDhcp6Config = DeviceInterface + ".Dhcp6Config" // readable o + DevicePropertyManaged = DeviceInterface + ".Managed" // readwrite b + DevicePropertyAutoconnect = DeviceInterface + ".Autoconnect" // readwrite b + DevicePropertyFirmwareMissing = DeviceInterface + ".FirmwareMissing" // readable b + DevicePropertyNmPluginMissing = DeviceInterface + ".NmPluginMissing" // readable b + DevicePropertyDeviceType = DeviceInterface + ".DeviceType" // readable u + DevicePropertyAvailableConnections = DeviceInterface + ".AvailableConnections" // readable ao + DevicePropertyPhysicalPortId = DeviceInterface + ".PhysicalPortId" // readable s + DevicePropertyMtu = DeviceInterface + ".Mtu" // readable u + DevicePropertyMetered = DeviceInterface + ".Metered" // readable u + DevicePropertyLldpNeighbors = DeviceInterface + ".LldpNeighbors" // readable aa{sv} + DevicePropertyReal = DeviceInterface + ".Real" // readable b + DevicePropertyIp4Connectivity = DeviceInterface + ".Ip4Connectivity" // readable u + + /* Signals */ + DeviceSignalStateChanged = "StateChanged" // u state, u reason + +) + +func DeviceFactory(objectPath dbus.ObjectPath) (Device, error) { + d, err := NewDevice(objectPath) + if err != nil { + return nil, err + } + + deviceType, err := d.GetPropertyDeviceType() + if err != nil { + return nil, err + } + + switch deviceType { + case NmDeviceTypeDummy: + return NewDeviceDummy(objectPath) + case NmDeviceTypeGeneric: + return NewDeviceGeneric(objectPath) + case NmDeviceTypeIpTunnel: + return NewDeviceIpTunnel(objectPath) + case NmDeviceTypeBridge: + return NewDeviceBridge(objectPath) + case NmDeviceTypeEthernet: + return NewDeviceWired(objectPath) + case NmDeviceTypeWifi: + return NewDeviceWireless(objectPath) + } + + return d, nil +} + +type Device interface { + GetPath() dbus.ObjectPath + + // Reapply Attempts to update the configuration of a device without deactivating it. NetworkManager has the concept of connections, which are profiles that contain the configuration for a networking device. Those connections are exposed via D-Bus as individual objects that can be created, modified and deleted. When activating such a settings-connection on a device, the settings-connection is cloned to become an applied-connection and used to configure the device (see GetAppliedConnection). Subsequent modification of the settings-connection don't propagate automatically to the device's applied-connection (with exception of the firewall-zone and the metered property). For the changes to take effect, you can either re-activate the settings-connection, or call Reapply. The Reapply call allows you to directly update the applied-connection and reconfigure the device. Reapply can also be useful if the currently applied-connection is equal to the connection that is about to be reapplied. This allows to reconfigure the device and revert external changes like removing or adding an IP address (which NetworkManager doesn't revert automatically because it is assumed that the user made these changes intentionally outside of NetworkManager). Reapply can make the applied-connection different from the settings-connection, just like updating the settings-connection can make them different. + // connection: The optional connection settings that will be reapplied on the device. If empty, the currently active settings-connection will be used. The connection cannot arbitrarly differ from the current applied-connection otherwise the call will fail. Only certain changes are supported, like adding or removing IP addresses. + // versionId: If non-zero, the current version id of the applied-connection must match. The current version id can be retrieved via GetAppliedConnection. This optional argument allows to catch concurrent modifications between the GetAppliedConnection call and Reapply. + // flags: Flags which would modify the behavior of the Reapply call. There are no flags defined currently and the users should use the value of 0. + Reapply(connection Connection, versionId uint64, flags uint32) error + + // Disconnect a device and prevents the device from automatically activating further connections without user intervention. + Disconnect() error + + // Delete a software device from NetworkManager and removes the interface from the system. The method returns an error when called for a hardware device. + Delete() error + + // GetPropertyUdi Operating-system specific transient device hardware identifier. This is an opaque string representing the underlying hardware for the device, and shouldn't be used to keep track of individual devices. For some device types (Bluetooth, Modems) it is an identifier used by the hardware service (ie bluez or ModemManager) to refer to that device, and client programs use it get additional information from those services which NM does not provide. The Udi is not guaranteed to be consistent across reboots or hotplugs of the hardware. If you're looking for a way to uniquely track each device in your application, use the object path. If you're looking for a way to track a specific piece of hardware across reboot or hotplug, use a MAC address or USB serial number. + GetPropertyUdi() (string, error) + + // GetPropertyInterface The name of the device's control (and often data) interface. Note that non UTF-8 characters are backslash escaped, so the resulting name may be longer then 15 characters. Use g_strcompress() to revert the escaping. + GetPropertyInterface() (string, error) + + // GetPropertyIpInterface The name of the device's data interface when available. This property may not refer to the actual data interface until the device has successfully established a data connection, indicated by the device's State becoming ACTIVATED. Note that non UTF-8 characters are backslash escaped, so the resulting name may be longer then 15 characters. Use g_strcompress() to revert the escaping. + GetPropertyIpInterface() (string, error) + + // GetPropertyDriver The driver handling the device. Non-UTF-8 sequences are backslash escaped. Use g_strcompress() to revert. + GetPropertyDriver() (string, error) + + // GetPropertyDriverVersion The version of the driver handling the device. Non-UTF-8 sequences are backslash escaped. Use g_strcompress() to revert. + GetPropertyDriverVersion() (string, error) + + // GetPropertyFirmwareVersion The firmware version for the device. Non-UTF-8 sequences are backslash escaped. Use g_strcompress() to revert. + GetPropertyFirmwareVersion() (string, error) + + // GetPropertyState The current state of the device. + GetPropertyState() (NmDeviceState, error) + + // GetPropertyActiveConnection Object path of an ActiveConnection object that "owns" this device during activation. The ActiveConnection object tracks the life-cycle of a connection to a specific network and implements the org.freedesktop.NetworkManager.Connection.Active D-Bus interface. + GetPropertyActiveConnection() (ActiveConnection, error) + + // GetPropertyIP4Config Object path of the Ip4Config object describing the configuration of the device. Only valid when the device is in the NM_DEVICE_STATE_ACTIVATED state. + GetPropertyIP4Config() (IP4Config, error) + + // GetPropertyDHCP4Config Object path of the Dhcp4Config object describing the DHCP options returned by the DHCP server. Only valid when the device is in the NM_DEVICE_STATE_ACTIVATED state. + GetPropertyDHCP4Config() (DHCP4Config, error) + + // GetPropertyIP6Config Object path of the Ip6Config object describing the configuration of the device. Only valid when the device is in the NM_DEVICE_STATE_ACTIVATED state. + GetPropertyIP6Config() (IP6Config, error) + + // GetPropertyDHCP6Config Object path of the Dhcp6Config object describing the DHCP options returned by the DHCP server. Only valid when the device is in the NM_DEVICE_STATE_ACTIVATED state. + GetPropertyDHCP6Config() (DHCP6Config, error) + + // GetPropertyManaged Whether this device is managed by NetworkManager. Setting this property has a similar effect to configuring the device as unmanaged via the keyfile.unmanaged-devices setting in NetworkManager.conf. Changes to this value are not persistent and lost after NetworkManager restart. + GetPropertyManaged() (bool, error) + SetPropertyManaged(bool) error + + // GetPropertyAutoConnect If TRUE, indicates the device is allowed to autoconnect. If FALSE, manual intervention is required before the device will automatically connect to a known network, such as activating a connection using the device, or setting this property to TRUE. This property cannot be set to TRUE for default-unmanaged devices, since they never autoconnect. + GetPropertyAutoConnect() (bool, error) + SetPropertyAutoConnect(bool) error + + // GetPropertyFirmwareMissing If TRUE, indicates the device is likely missing firmware necessary for its operation. + GetPropertyFirmwareMissing() (bool, error) + + // GetPropertyNmPluginMissing If TRUE, indicates the NetworkManager plugin for the device is likely missing or misconfigured. + GetPropertyNmPluginMissing() (bool, error) + + // GetPropertyDeviceType The general type of the network device; ie Ethernet, Wi-Fi, etc. + GetPropertyDeviceType() (NmDeviceType, error) + + // GetPropertyAvailableConnections An array of object paths of every configured connection that is currently 'available' through this device. + GetPropertyAvailableConnections() ([]Connection, error) + + // GetPropertyPhysicalPortId If non-empty, an (opaque) indicator of the physical network port associated with the device. This can be used to recognize when two seemingly-separate hardware devices are actually just different virtual interfaces to the same physical port. + GetPropertyPhysicalPortId() (string, error) + + // GetPropertyMtu The device MTU (maximum transmission unit). + GetPropertyMtu() (uint32, error) + + // GetPropertyReal True if the device exists, or False for placeholder devices that do not yet exist but could be automatically created by NetworkManager if one of their AvailableConnections was activated. + GetPropertyReal() (bool, error) + + // The result of the last IPv4 connectivity check. + GetPropertyIp4Connectivity() (NmConnectivity, error) + + SubscribeState(receiver chan DeviceStateChange, exit chan struct{}) (err error) + + MarshalJSON() ([]byte, error) +} + +func NewDevice(objectPath dbus.ObjectPath) (Device, error) { + var d device + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type device struct { + dbusBase +} + +func (d *device) GetPath() dbus.ObjectPath { + return d.obj.Path() +} + +func (d *device) Reapply(connection Connection, versionId uint64, flags uint32) error { + return d.call(DeviceReapply, connection, versionId, flags) +} + +func (d *device) Disconnect() error { + return d.call(DeviceDisconnect) +} + +func (d *device) Delete() error { + return d.call(DeviceDelete) +} + +func (d *device) GetPropertyUdi() (string, error) { + return d.getStringProperty(DevicePropertyUdi) +} + +func (d *device) GetPropertyInterface() (string, error) { + return d.getStringProperty(DevicePropertyInterface) +} + +func (d *device) GetPropertyIpInterface() (string, error) { + return d.getStringProperty(DevicePropertyIpInterface) +} + +func (d *device) GetPropertyDriver() (string, error) { + return d.getStringProperty(DevicePropertyDriver) +} + +func (d *device) GetPropertyDriverVersion() (string, error) { + return d.getStringProperty(DevicePropertyDriverVersion) +} + +func (d *device) GetPropertyFirmwareVersion() (string, error) { + return d.getStringProperty(DevicePropertyFirmwareVersion) +} + +func (d *device) GetPropertyState() (NmDeviceState, error) { + r, err := d.getUint32Property(DevicePropertyState) + if err != nil { + return NmDeviceStateFailed, err + } + return NmDeviceState(r), nil +} + +func (d *device) GetPropertyActiveConnection() (ActiveConnection, error) { + path, err := d.getObjectProperty(DevicePropertyActiveConnection) + if err != nil || path == "/" { + return nil, err + } + + return NewActiveConnection(path) +} + +func (d *device) GetPropertyIP4Config() (IP4Config, error) { + path, err := d.getObjectProperty(DevicePropertyIp4Config) + if err != nil || path == "/" { + return nil, err + } + + return NewIP4Config(path) +} + +func (d *device) GetPropertyDHCP4Config() (DHCP4Config, error) { + path, err := d.getObjectProperty(DevicePropertyDhcp4Config) + if err != nil || path == "/" { + return nil, err + } + + return NewDHCP4Config(path) +} + +func (d *device) GetPropertyIP6Config() (IP6Config, error) { + path, err := d.getObjectProperty(DevicePropertyIp6Config) + if err != nil || path == "/" { + return nil, err + } + + return NewIP6Config(path) +} + +func (d *device) GetPropertyDHCP6Config() (DHCP6Config, error) { + path, err := d.getObjectProperty(DevicePropertyDhcp6Config) + if err != nil || path == "/" { + return nil, err + } + + return NewDHCP6Config(path) +} + +func (d *device) GetPropertyManaged() (bool, error) { + return d.getBoolProperty(DevicePropertyManaged) +} + +func (d *device) SetPropertyManaged(managed bool) error { + return d.setProperty(DevicePropertyManaged, managed) +} + +func (d *device) GetPropertyAutoConnect() (bool, error) { + return d.getBoolProperty(DevicePropertyAutoconnect) +} + +func (d *device) SetPropertyAutoConnect(managed bool) error { + return d.setProperty(DevicePropertyAutoconnect, managed) +} + +func (d *device) GetPropertyFirmwareMissing() (bool, error) { + return d.getBoolProperty(DevicePropertyFirmwareMissing) +} + +func (d *device) GetPropertyNmPluginMissing() (bool, error) { + return d.getBoolProperty(DevicePropertyNmPluginMissing) +} + +func (d *device) GetPropertyDeviceType() (NmDeviceType, error) { + v, err := d.getUint32Property(DevicePropertyDeviceType) + return NmDeviceType(v), err +} + +func (d *device) GetPropertyAvailableConnections() ([]Connection, error) { + connPaths, err := d.getSliceObjectProperty(DevicePropertyAvailableConnections) + if err != nil { + return nil, err + } + + conns := make([]Connection, len(connPaths)) + for i, path := range connPaths { + conns[i], err = NewConnection(path) + if err != nil { + return conns, err + } + } + + return conns, nil +} + +func (d *device) GetPropertyPhysicalPortId() (string, error) { + return d.getStringProperty(DevicePropertyPhysicalPortId) +} + +func (d *device) GetPropertyMtu() (uint32, error) { + return d.getUint32Property(DevicePropertyMtu) +} + +func (d *device) GetPropertyReal() (bool, error) { + return d.getBoolProperty(DevicePropertyReal) +} + +func (d *device) GetPropertyIp4Connectivity() (NmConnectivity, error) { + u, err := d.getUint32Property(DevicePropertyIp4Connectivity) + return NmConnectivity(u), err +} + +func (d *device) marshalMap() (map[string]interface{}, error) { + Interface, err := d.GetPropertyInterface() + if err != nil { + return nil, err + } + IpInterface, err := d.GetPropertyIpInterface() + if err != nil { + return nil, err + } + State, err := d.GetPropertyState() + if err != nil { + return nil, err + } + IP4Config, err := d.GetPropertyIP4Config() + if err != nil { + return nil, err + } + DHCP4Config, err := d.GetPropertyDHCP4Config() + if err != nil { + return nil, err + } + DeviceType, err := d.GetPropertyDeviceType() + if err != nil { + return nil, err + } + AvailableConnections, err := d.GetPropertyAvailableConnections() + if err != nil { + return nil, err + } + + return map[string]interface{}{ + "Interface": Interface, + "IP interface": IpInterface, + "State": State.String(), + "IP4Config": IP4Config, + "DHCP4Config": DHCP4Config, + "DeviceType": DeviceType.String(), + "AvailableConnections": AvailableConnections, + }, nil +} + +type DeviceStateChange struct { + Path dbus.ObjectPath + State NmDeviceState + Reason NmDeviceStateReason +} + +func (d *device) SubscribeState(receiver chan DeviceStateChange, exit chan struct{}) (err error) { + + channel := make(chan *dbus.Signal, 1) + + d.conn.Signal(channel) + + err = d.conn.AddMatchSignal( + dbus.WithMatchInterface(DeviceInterface), + dbus.WithMatchMember(DeviceSignalStateChanged), + dbus.WithMatchObjectPath(d.GetPath()), + ) + if err != nil { + return err + } + + go func() { + for { + select { + case signal, ok := <-channel: + if !ok { + err = fmt.Errorf("connection closed for %s", DeviceSignalStateChanged) + return + } + + if signal.Name != DeviceInterface+"."+DeviceSignalStateChanged { + continue + } + + stateChange := DeviceStateChange{ + Path: signal.Path, + State: NmDeviceState(signal.Body[0].(uint32)), + Reason: NmDeviceStateReason(signal.Body[1].(uint32)), + } + + receiver <- stateChange + + case <-exit: + d.conn.RemoveSignal(channel) + close(channel) + return + } + } + }() + + return +} + +func (d *device) MarshalJSON() ([]byte, error) { + m, err := d.marshalMap() + if err != nil { + return nil, err + } + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceBridge.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceBridge.go new file mode 100644 index 0000000..2a7d17b --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceBridge.go @@ -0,0 +1,75 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceBridgeInterface = DeviceInterface + ".Bridge" + + // Properties + DeviceBridgePropertyHwAddress = DeviceBridgeInterface + ".HwAddress" // readable s + DeviceBridgePropertySlaves = DeviceBridgeInterface + ".Slaves" // readable as + DeviceBridgePropertyCarrier = DeviceBridgeInterface + ".Carrier" // readable b +) + +type DeviceBridge interface { + Device + + // GetPropertyHwAddress Active hardware address of the device. + GetPropertyHwAddress() (string, error) + + // GetPropertySlaves Array of paths of enslaved and active devices. + // DEPRECATED. Use the "Ports" property in "org.freedesktop.NetworkManager.Device" instead which exists since version NetworkManager 1.34.0. + GetPropertySlaves() ([]Device, error) + + // GetPropertyCarrier Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not). + // DEPRECATED: check for the "carrier" flag in the "InterfaceFlags" property on the "org.freedesktop.NetworkManager.Device" interface. + GetPropertyCarrier() (bool, error) +} + +func NewDeviceBridge(objectPath dbus.ObjectPath) (DeviceBridge, error) { + var d deviceBridge + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceBridge struct { + device +} + +func (d *deviceBridge) GetPropertyHwAddress() (string, error) { + return d.getStringProperty(DeviceBridgePropertyHwAddress) +} + +func (d *deviceBridge) GetPropertySlaves() ([]Device, error) { + paths, err := d.getSliceObjectProperty(DeviceBridgePropertySlaves) + if err != nil { + return nil, err + } + devices := make([]Device, len(paths)) + for i, path := range paths { + devices[i], err = DeviceFactory(path) + if err != nil { + return nil, err + } + } + return devices, nil +} + +func (d *deviceBridge) GetPropertyCarrier() (bool, error) { + return d.getBoolProperty(DeviceBridgePropertyCarrier) +} + +func (d *deviceBridge) MarshalJSON() ([]byte, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["HwAddress"], _ = d.GetPropertyHwAddress() + m["Slaves"], _ = d.GetPropertySlaves() + m["Carrier"], _ = d.GetPropertyCarrier() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceDummy.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceDummy.go new file mode 100644 index 0000000..c92a396 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceDummy.go @@ -0,0 +1,44 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceDummyInterface = DeviceInterface + ".Dummy" + + /* Properties */ + DeviceDummyPropertyHwAddress = DeviceDummyInterface + ".HwAddress" // readable s +) + +type DeviceDummy interface { + Device + + // Hardware address of the device. + GetPropertyHwAddress() (string, error) +} + +func NewDeviceDummy(objectPath dbus.ObjectPath) (DeviceDummy, error) { + var d deviceDummy + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceDummy struct { + device +} + +func (d *deviceDummy) GetPropertyHwAddress() (string, error) { + return d.getStringProperty(DeviceDummyPropertyHwAddress) +} + +func (d *deviceDummy) MarshalJSON() ([]byte, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["HwAddress"], _ = d.GetPropertyHwAddress() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceGeneric.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceGeneric.go new file mode 100644 index 0000000..7e736bd --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceGeneric.go @@ -0,0 +1,53 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceGenericInterface = DeviceInterface + ".Generic" + + // Properties + DeviceGenericPropertyHwAddress = DeviceGenericInterface + ".HwAddress" // readable s + DeviceGenericPropertyTypeDescription = DeviceGenericInterface + ".TypeDescription" // readable s +) + +type DeviceGeneric interface { + Device + + // GetPropertyHwAddress Active hardware address of the device. + GetPropertyHwAddress() (string, error) + + // GetPropertyTypeDescription A (non-localized) description of the interface type, if known. + GetPropertyTypeDescription() (string, error) +} + +func NewDeviceGeneric(objectPath dbus.ObjectPath) (DeviceGeneric, error) { + var d deviceGeneric + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceGeneric struct { + device +} + +func (d *deviceGeneric) GetPropertyHwAddress() (string, error) { + return d.getStringProperty(DeviceGenericPropertyHwAddress) +} + +func (d *deviceGeneric) GetPropertyTypeDescription() (string, error) { + return d.getStringProperty(DeviceGenericPropertyTypeDescription) +} + +func (d *deviceGeneric) MarshalJSON() ([]byte, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["HwAddress"], _ = d.GetPropertyHwAddress() + m["TypeDescription"], _ = d.GetPropertyTypeDescription() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceIpTunnel.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceIpTunnel.go new file mode 100644 index 0000000..65f732b --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceIpTunnel.go @@ -0,0 +1,150 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceIpTunnelInterface = DeviceInterface + ".IPTunnel" + + // Properties + DeviceIpTunnelPropertyHwAddress = DeviceIpTunnelInterface + "HwAddress" // readable s + DeviceIpTunnelPropertyMode = DeviceIpTunnelInterface + ".Mode" // readable u + DeviceIpTunnelPropertyParent = DeviceIpTunnelInterface + ".Parent" // readable o + DeviceIpTunnelPropertyLocal = DeviceIpTunnelInterface + ".Local" // readable s + DeviceIpTunnelPropertyRemote = DeviceIpTunnelInterface + ".Remote" // readable s + DeviceIpTunnelPropertyTtl = DeviceIpTunnelInterface + ".Ttl" // readable y + DeviceIpTunnelPropertyTos = DeviceIpTunnelInterface + ".Tos" // readable y + DeviceIpTunnelPropertyPathMtuDiscovery = DeviceIpTunnelInterface + ".PathMtuDiscovery" // readable b + DeviceIpTunnelPropertyInputKey = DeviceIpTunnelInterface + ".InputKey" // readable s + DeviceIpTunnelPropertyOutputKey = DeviceIpTunnelInterface + ".OutputKey" // readable s + DeviceIpTunnelPropertyEncapsulationLimit = DeviceIpTunnelInterface + ".EncapsulationLimit" // readable y + DeviceIpTunnelPropertyFlowLabel = DeviceIpTunnelInterface + ".FlowLabel" // readable u + DeviceIpTunnelPropertyFlags = DeviceIpTunnelInterface + ".Flags" // readable u + +) + +type DeviceIpTunnel interface { + Device + + // GetPropertyMode The tunneling mode + GetPropertyMode() (uint32, error) + + // GetPropertyParent The object path of the parent device. + GetPropertyParent() (Device, error) + + // GetPropertyLocal The local endpoint of the tunnel. + GetPropertyLocal() (string, error) + + // GetPropertyRemote The remote endpoint of the tunnel. + GetPropertyRemote() (string, error) + + // GetPropertyTtl The TTL assigned to tunneled packets. 0 is a special value meaning that packets inherit the TTL value + GetPropertyTtl() (uint8, error) + + // GetPropertyTos The type of service (IPv4) or traffic class (IPv6) assigned to tunneled packets. + GetPropertyTos() (uint8, error) + + // GetPropertyPathMtuDiscovery Whether path MTU discovery is enabled on this tunnel. + GetPropertyPathMtuDiscovery() (bool, error) + + // GetPropertyInputKey The key used for incoming packets. + GetPropertyInputKey() (string, error) + + // GetPropertyOutputKey The key used for outgoing packets. + GetPropertyOutputKey() (string, error) + + // GetPropertyEncapsulationLimit How many additional levels of encapsulation are permitted to be prepended to packets. This property applies only to IPv6 tunnels. + GetPropertyEncapsulationLimit() (uint8, error) + + // GetPropertyFlowLabel The flow label to assign to tunnel packets. This property applies only to IPv6 tunnels. + GetPropertyFlowLabel() (uint32, error) + + // GetPropertyFlags Tunnel flags. + GetPropertyFlags() (uint32, error) +} + +func NewDeviceIpTunnel(objectPath dbus.ObjectPath) (DeviceIpTunnel, error) { + var d deviceIpTunnel + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceIpTunnel struct { + device +} + +func (d *deviceIpTunnel) GetPropertyMode() (uint32, error) { + return d.getUint32Property(DeviceIpTunnelPropertyMode) +} + +func (d *deviceIpTunnel) GetPropertyParent() (Device, error) { + path, err := d.getObjectProperty(DeviceIpTunnelPropertyParent) + if err != nil || path == "/" { + return nil, err + } + + return DeviceFactory(path) +} + +func (d *deviceIpTunnel) GetPropertyLocal() (string, error) { + return d.getStringProperty(DeviceIpTunnelPropertyLocal) +} + +func (d *deviceIpTunnel) GetPropertyRemote() (string, error) { + return d.getStringProperty(DeviceIpTunnelPropertyRemote) +} + +func (d *deviceIpTunnel) GetPropertyTtl() (uint8, error) { + return d.getUint8Property(DeviceIpTunnelPropertyTtl) +} + +func (d *deviceIpTunnel) GetPropertyTos() (uint8, error) { + return d.getUint8Property(DeviceIpTunnelPropertyTos) +} + +func (d *deviceIpTunnel) GetPropertyPathMtuDiscovery() (bool, error) { + return d.getBoolProperty(DeviceIpTunnelPropertyPathMtuDiscovery) +} + +func (d *deviceIpTunnel) GetPropertyInputKey() (string, error) { + return d.getStringProperty(DeviceIpTunnelPropertyInputKey) +} + +func (d *deviceIpTunnel) GetPropertyOutputKey() (string, error) { + return d.getStringProperty(DeviceIpTunnelPropertyOutputKey) +} + +func (d *deviceIpTunnel) GetPropertyEncapsulationLimit() (uint8, error) { + return d.getUint8Property(DeviceIpTunnelPropertyEncapsulationLimit) +} + +func (d *deviceIpTunnel) GetPropertyFlowLabel() (uint32, error) { + return d.getUint32Property(DeviceIpTunnelPropertyFlowLabel) +} + +func (d *deviceIpTunnel) GetPropertyFlags() (uint32, error) { + return d.getUint32Property(DeviceIpTunnelPropertyFlags) +} + +func (d *deviceIpTunnel) MarshalJSON() ([]uint8, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["Mode"], _ = d.GetPropertyMode() + m["Parent"], _ = d.GetPropertyParent() + m["Local"], _ = d.GetPropertyLocal() + m["Remote"], _ = d.GetPropertyRemote() + m["Ttl"], _ = d.GetPropertyTtl() + m["Tos"], _ = d.GetPropertyTos() + m["PathMtuDiscovery"], _ = d.GetPropertyPathMtuDiscovery() + m["InputKey"], _ = d.GetPropertyInputKey() + m["OutputKey"], _ = d.GetPropertyOutputKey() + m["EncapsulationLimit"], _ = d.GetPropertyEncapsulationLimit() + m["FlowLabel"], _ = d.GetPropertyFlowLabel() + m["Flags"], _ = d.GetPropertyFlags() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceStatistics.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceStatistics.go new file mode 100644 index 0000000..c72ab0a --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceStatistics.go @@ -0,0 +1,74 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceStatisticsInterface = DeviceInterface + ".Statistics" + + // Properties + DeviceStatisticsPropertyRefreshRateMs = DeviceStatisticsInterface + ".RefreshRateMs" // readwrite u + DeviceStatisticsPropertyTxBytes = DeviceStatisticsInterface + ".TxBytes" // readable t + DeviceStatisticsPropertyRxBytes = DeviceStatisticsInterface + ".RxBytes" // readable t +) + +type DeviceStatistics interface { + GetPath() dbus.ObjectPath + + // GetPropertyRefreshRateMs Refresh rate of the rest of properties of this interface. The properties are guaranteed to be refreshed each RefreshRateMs milliseconds in case the underlying counter has changed too. If zero, there is no guaranteed refresh rate of the properties. + GetPropertyRefreshRateMs() (uint32, error) + + SetPropertyRefreshRateMs(uint32) error + + // GetPropertyTxBytes Number of transmitted bytes + GetPropertyTxBytes() (uint64, error) + + // GetPropertyRxBytes Number of received bytes + GetPropertyRxBytes() (uint64, error) +} + +func NewDeviceStatistics(objectPath dbus.ObjectPath) (DeviceStatistics, error) { + var d deviceStatistics + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceStatistics struct { + dbusBase +} + +func (d *deviceStatistics) GetPath() dbus.ObjectPath { + return d.obj.Path() +} + +func (d *deviceStatistics) GetPropertyRefreshRateMs() (uint32, error) { + return d.getUint32Property(DeviceStatisticsPropertyRefreshRateMs) +} + +func (d *deviceStatistics) SetPropertyRefreshRateMs(rate uint32) error { + return d.setProperty(DeviceStatisticsPropertyRefreshRateMs, rate) +} + +func (d *deviceStatistics) GetPropertyTxBytes() (uint64, error) { + return d.getUint64Property(DeviceStatisticsPropertyTxBytes) +} + +func (d *deviceStatistics) GetPropertyRxBytes() (uint64, error) { + return d.getUint64Property(DeviceStatisticsPropertyRxBytes) +} + +func (d *deviceStatistics) marshalMap() map[string]interface{} { + return map[string]interface{}{} +} + +func (d *deviceStatistics) MarshalJSON() ([]byte, error) { + m := make(map[string]interface{}) + + m["RefreshRateMs"], _ = d.GetPropertyRefreshRateMs() + m["TxBytes"], _ = d.GetPropertyTxBytes() + m["RxBytes"], _ = d.GetPropertyRxBytes() + + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWired.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWired.go new file mode 100644 index 0000000..65e3d63 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWired.go @@ -0,0 +1,80 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceWiredInterface = DeviceInterface + ".Wired" + + // Properties + DeviceWiredPropertyHwAddress = DeviceWiredInterface + ".HwAddress" // readable s + DeviceWiredPropertyPermHwAddress = DeviceWiredInterface + ".PermHwAddress" // readable s + DeviceWiredPropertySpeed = DeviceWiredInterface + ".Speed" // readable u + DeviceWiredPropertyS390Subchannels = DeviceWiredInterface + ".S390Subchannels" // readable as + DeviceWiredPropertyCarrier = DeviceWiredInterface + ".Carrier" // readable b +) + +type DeviceWired interface { + Device + + // GetPropertyHwAddress Active hardware address of the device. + GetPropertyHwAddress() (string, error) + + // GetPropertyPermHwAddress Permanent hardware address of the device. + GetPropertyPermHwAddress() (string, error) + + // GetPropertySpeed Design speed of the device, in megabits/second (Mb/s). + GetPropertySpeed() (uint32, error) + + // GetPropertyS390Subchannels Array of S/390 subchannels for S/390 or z/Architecture devices. + GetPropertyS390Subchannels() ([]string, error) + + // GetPropertyCarrier Indicates whether the physical carrier is found (e.g. whether a cable is plugged in or not). + GetPropertyCarrier() (bool, error) +} + +func NewDeviceWired(objectPath dbus.ObjectPath) (DeviceWired, error) { + var d deviceWired + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceWired struct { + device +} + +func (d *deviceWired) GetPropertyHwAddress() (string, error) { + return d.getStringProperty(DeviceWiredPropertyHwAddress) +} + +func (d *deviceWired) GetPropertyPermHwAddress() (string, error) { + return d.getStringProperty(DeviceWiredPropertyPermHwAddress) +} + +func (d *deviceWired) GetPropertySpeed() (uint32, error) { + return d.getUint32Property(DeviceWiredPropertySpeed) +} + +func (d *deviceWired) GetPropertyS390Subchannels() ([]string, error) { + return d.getSliceStringProperty(DeviceWiredPropertyS390Subchannels) +} + +func (d *deviceWired) GetPropertyCarrier() (bool, error) { + return d.getBoolProperty(DeviceWiredPropertyCarrier) +} + +func (d *deviceWired) MarshalJSON() ([]byte, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["HwAddress"], _ = d.GetPropertyHwAddress() + m["PermHwAddress"], _ = d.GetPropertyPermHwAddress() + m["Speed"], _ = d.GetPropertySpeed() + m["S390Subchannels"], _ = d.GetPropertyS390Subchannels() + m["Carrier"], _ = d.GetPropertyCarrier() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWireless.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWireless.go new file mode 100644 index 0000000..22977e5 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DeviceWireless.go @@ -0,0 +1,193 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + DeviceWirelessInterface = DeviceInterface + ".Wireless" + + // Methods + DeviceWirelessGetAccessPoints = DeviceWirelessInterface + ".GetAccessPoints" + DeviceWirelessGetAllAccessPoints = DeviceWirelessInterface + ".GetAllAccessPoints" + DeviceWirelessRequestScan = DeviceWirelessInterface + ".RequestScan" + + // Properties + DeviceWirelessPropertyHwAddress = DeviceWirelessInterface + ".HwAddress" // readable s + DeviceWirelessPropertyPermHwAddress = DeviceWirelessInterface + ".PermHwAddress" // readable s + DeviceWirelessPropertyMode = DeviceWirelessInterface + ".Mode" // readable u + DeviceWirelessPropertyBitrate = DeviceWirelessInterface + ".Bitrate" // readable u + DeviceWirelessPropertyAccessPoints = DeviceWirelessInterface + ".AccessPoints" // readable ao + DeviceWirelessPropertyActiveAccessPoint = DeviceWirelessInterface + ".ActiveAccessPoint" // readable o + DeviceWirelessPropertyWirelessCapabilities = DeviceWirelessInterface + ".WirelessCapabilities" // readable u + DeviceWirelessPropertyLastScan = DeviceWirelessInterface + ".LastScan" // readable x +) + +type DeviceWireless interface { + Device + + // GetAccessPoints gets the list of access points visible to this device. + // Note that this list does not include access points which hide their SSID. + // To retrieve a list of all access points (including hidden ones) use the + // GetAllAccessPoints() method. + GetAccessPoints() ([]AccessPoint, error) + + // GetAllAccessPoints gets the list of all access points visible to this + // device, including hidden ones for which the SSID is not yet known. + GetAllAccessPoints() ([]AccessPoint, error) + + // RequestScan Request the device to scan. To know when the scan is finished, use the + // "PropertiesChanged" signal from "org.freedesktop.DBus.Properties" to listen + // to changes to the "LastScan" property. + RequestScan() error + + // GetPropertyHwAddress The active hardware address of the device. + GetPropertyHwAddress() (string, error) + + // GetPropertyPermHwAddress The permanent hardware address of the device. + GetPropertyPermHwAddress() (string, error) + + // GetPropertyMode The operating mode of the wireless device. + GetPropertyMode() (Nm80211Mode, error) + + // GetPropertyBitrate The bit rate currently used by the wireless device, in kilobits/second (Kb/s). + GetPropertyBitrate() (uint32, error) + + // GetPropertyAccessPoints List of object paths of access point visible to this wireless device. + GetPropertyAccessPoints() ([]AccessPoint, error) + + // GetPropertyActiveAccessPoint Object path of the access point currently used by the wireless device. + GetPropertyActiveAccessPoint() (AccessPoint, error) + + // GetPropertyWirelessCapabilities The capabilities of the wireless device. + GetPropertyWirelessCapabilities() (uint32, error) + + // GetPropertyLastScan The timestamp (in CLOCK_BOOTTIME milliseconds) for the last finished + // network scan. A value of -1 means the device never scanned for access + // points. + GetPropertyLastScan() (int64, error) +} + +func NewDeviceWireless(objectPath dbus.ObjectPath) (DeviceWireless, error) { + var d deviceWireless + return &d, d.init(NetworkManagerInterface, objectPath) +} + +type deviceWireless struct { + device +} + +func (d *deviceWireless) GetAccessPoints() ([]AccessPoint, error) { + var apPaths []dbus.ObjectPath + err := d.callWithReturn(&apPaths, DeviceWirelessGetAccessPoints) + + if err != nil { + return nil, err + } + + aps := make([]AccessPoint, len(apPaths)) + + for i, path := range apPaths { + aps[i], err = NewAccessPoint(path) + if err != nil { + return aps, err + } + } + + return aps, nil +} + +func (d *deviceWireless) GetAllAccessPoints() ([]AccessPoint, error) { + var apPaths []dbus.ObjectPath + err := d.callWithReturn(&apPaths, DeviceWirelessGetAllAccessPoints) + + if err != nil { + return nil, err + } + + aps := make([]AccessPoint, len(apPaths)) + + for i, path := range apPaths { + aps[i], err = NewAccessPoint(path) + if err != nil { + return aps, err + } + } + + return aps, nil +} + +func (d *deviceWireless) RequestScan() error { + var options map[string]interface{} + return d.obj.Call(DeviceWirelessRequestScan, 0, options).Store() +} + +func (d *deviceWireless) GetPropertyHwAddress() (string, error) { + return d.getStringProperty(DeviceWirelessPropertyHwAddress) +} + +func (d *deviceWireless) GetPropertyPermHwAddress() (string, error) { + return d.getStringProperty(DeviceWirelessPropertyPermHwAddress) +} + +func (d *deviceWireless) GetPropertyMode() (Nm80211Mode, error) { + v, err := d.getUint32Property(DeviceWirelessPropertyMode) + return Nm80211Mode(v), err +} + +func (d *deviceWireless) GetPropertyBitrate() (uint32, error) { + return d.getUint32Property(DeviceWirelessPropertyBitrate) +} + +func (d *deviceWireless) GetPropertyAccessPoints() ([]AccessPoint, error) { + apPaths, err := d.getSliceObjectProperty(DeviceWirelessPropertyAccessPoints) + if err != nil { + return nil, err + } + + ap := make([]AccessPoint, len(apPaths)) + for i, path := range apPaths { + ap[i], err = NewAccessPoint(path) + if err != nil { + return ap, err + } + } + + return ap, nil +} + +func (d *deviceWireless) GetPropertyActiveAccessPoint() (AccessPoint, error) { + path, err := d.getObjectProperty(DeviceWirelessPropertyActiveAccessPoint) + if err != nil || path == "/" { + return nil, err + } + + return NewAccessPoint(path) +} + +func (d *deviceWireless) GetPropertyWirelessCapabilities() (uint32, error) { + return d.getUint32Property(DeviceWirelessPropertyWirelessCapabilities) +} + +func (d *deviceWireless) GetPropertyLastScan() (int64, error) { + return d.getInt64Property(DeviceWirelessPropertyLastScan) +} + +func (d *deviceWireless) MarshalJSON() ([]byte, error) { + m, err := d.device.marshalMap() + if err != nil { + return nil, err + } + + m["AccessPoints"], _ = d.GetPropertyAccessPoints() + m["HwAddress"], _ = d.GetPropertyHwAddress() + m["PermHwAddress"], _ = d.GetPropertyPermHwAddress() + m["Mode"], _ = d.GetPropertyMode() + m["Bitrate"], _ = d.GetPropertyBitrate() + m["ActiveAccessPoint"], _ = d.GetPropertyActiveAccessPoint() + m["WirelessCapabilities"], _ = d.GetPropertyWirelessCapabilities() + m["LastScan"], _ = d.GetPropertyLastScan() + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/DnsManager.go b/vendor/github.com/Wifx/gonetworkmanager/v2/DnsManager.go new file mode 100644 index 0000000..cbedfa5 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/DnsManager.go @@ -0,0 +1,96 @@ +package gonetworkmanager + +import ( + "errors" + + "github.com/godbus/dbus/v5" +) + +const ( + DnsManagerInterface = NetworkManagerInterface + ".DnsManager" + DnsManagerObjectPath = "/org/freedesktop/NetworkManager/DnsManager" + + /* Property */ + DnsManagerPropertyMode = DnsManagerInterface + ".Mode" // readable s + DnsManagerPropertyRcManager = DnsManagerInterface + ".RcManager" // readable s + DnsManagerPropertyConfiguration = DnsManagerInterface + ".Configuration" // readable aa{sv} +) + +type DnsConfigurationData struct { + Nameservers []string + Priority int32 + Interface string + Vpn bool +} + +type DnsManager interface { + GetPath() dbus.ObjectPath + GetPropertyMode() (string, error) + GetPropertyRcManager() (string, error) + GetPropertyConfiguration() ([]DnsConfigurationData, error) +} + +type dnsManager struct { + dbusBase +} + +func NewDnsManager() (DnsManager, error) { + var d dnsManager + return &d, d.init(NetworkManagerInterface, DnsManagerObjectPath) +} + +func (d *dnsManager) GetPath() dbus.ObjectPath { + return d.obj.Path() +} + +func (d *dnsManager) GetPropertyMode() (string, error) { + return d.getStringProperty(DnsManagerPropertyMode) +} + +func (d *dnsManager) GetPropertyRcManager() (string, error) { + return d.getStringProperty(DnsManagerPropertyRcManager) +} + +func (d *dnsManager) GetPropertyConfiguration() ([]DnsConfigurationData, error) { + configurations, err := d.getSliceMapStringVariantProperty(DnsManagerPropertyConfiguration) + if err != nil { + return nil, err + } + + ret := make([]DnsConfigurationData, len(configurations)) + for i, conf := range configurations { + if serversVar, exist := conf["nameservers"]; exist { + servers, ok := serversVar.Value().([]string) + if !ok { + return nil, errors.New("unexpected variant type for nameservers") + } + ret[i].Nameservers = servers + } + + if priorityVar, exist := conf["priority"]; exist { + priority, ok := priorityVar.Value().(int32) + if !ok { + return nil, errors.New("unexpected variant type for priority") + } + ret[i].Priority = priority + } + + if interfaceVar, exist := conf["interface"]; exist { + iface, ok := interfaceVar.Value().(string) + if !ok { + return nil, errors.New("unexpected variant type for interface") + } + ret[i].Interface = iface + } + + if vpnVar, exist := conf["vpn"]; exist { + vpn, ok := vpnVar.Value().(bool) + if !ok { + return nil, errors.New("unexpected variant type for vpn") + } + ret[i].Vpn = vpn + } + } + + return ret, nil +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/IP4Config.go b/vendor/github.com/Wifx/gonetworkmanager/v2/IP4Config.go new file mode 100644 index 0000000..2746f1a --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/IP4Config.go @@ -0,0 +1,321 @@ +package gonetworkmanager + +import ( + "encoding/json" + "errors" + + "github.com/godbus/dbus/v5" +) + +const ( + IP4ConfigInterface = NetworkManagerInterface + ".IP4Config" + + /* Properties */ + IP4ConfigPropertyAddresses = IP4ConfigInterface + ".Addresses" // readable aau + IP4ConfigPropertyAddressData = IP4ConfigInterface + ".AddressData" // readable aa{sv} + IP4ConfigPropertyGateway = IP4ConfigInterface + ".Gateway" // readable s + IP4ConfigPropertyRoutes = IP4ConfigInterface + ".Routes" // readable aau + IP4ConfigPropertyRouteData = IP4ConfigInterface + ".RouteData" // readable aa{sv} + IP4ConfigPropertyNameservers = IP4ConfigInterface + ".Nameservers" // readable au + IP4ConfigPropertyNameserverData = IP4ConfigInterface + ".NameserverData" // readable aa{sv} + IP4ConfigPropertyDomains = IP4ConfigInterface + ".Domains" // readable as + IP4ConfigPropertySearches = IP4ConfigInterface + ".Searches" // readable as + IP4ConfigPropertyDnsOptions = IP4ConfigInterface + ".DnsOptions" // readable as + IP4ConfigPropertyDnsPriority = IP4ConfigInterface + ".DnsPriority" // readable i + IP4ConfigPropertyWinsServers = IP4ConfigInterface + ".WinsServers" // readable au + IP4ConfigPropertyWinsServerData = IP4ConfigInterface + ".WinsServerData" // readable as +) + +// Deprecated: use IP4AddressData instead +type IP4Address struct { + Address string + Prefix uint8 + Gateway string +} + +type IP4AddressData struct { + Address string + Prefix uint8 +} + +// Deprecated: use IP4RouteData instead +type IP4Route struct { + Route string + Prefix uint8 + NextHop string + Metric uint8 +} + +type IP4RouteData struct { + Destination string + Prefix uint8 + NextHop string + Metric uint8 + AdditionalAttributes map[string]string +} + +type IP4NameserverData struct { + Address string +} + +type IP4Config interface { + // GetPropertyAddresses Array of arrays of IPv4 address/prefix/gateway. All 3 elements of each array are in network byte order. Essentially: [(addr, prefix, gateway), (addr, prefix, gateway), ...] + // Deprecated: use AddressData and Gateway + GetPropertyAddresses() ([]IP4Address, error) + + // GetPropertyAddressData Array of IP address data objects. All addresses will include "address" (an IP address string), and "prefix" (a uint). Some addresses may include additional attributes. + GetPropertyAddressData() ([]IP4AddressData, error) + + // GetPropertyGateway The gateway in use. + GetPropertyGateway() (string, error) + + // GetPropertyRoutes Arrays of IPv4 route/prefix/next-hop/metric. All 4 elements of each tuple are in network byte order. 'route' and 'next hop' are IPv4 addresses, while prefix and metric are simple unsigned integers. Essentially: [(route, prefix, next-hop, metric), (route, prefix, next-hop, metric), ...] + // Deprecated: use RouteData + GetPropertyRoutes() ([]IP4Route, error) + + // GetPropertyRouteData Array of IP route data objects. All routes will include "dest" (an IP address string) and "prefix" (a uint). Some routes may include "next-hop" (an IP address string), "metric" (a uint), and additional attributes. + GetPropertyRouteData() ([]IP4RouteData, error) + + // GetPropertyNameservers The nameservers in use. + // Deprecated: use NameserverData + GetPropertyNameservers() ([]string, error) + + // GetPropertyNameserverData The nameservers in use. Currently only the value "address" is recognized (with an IP address string). + GetPropertyNameserverData() ([]IP4NameserverData, error) + + // GetPropertyDomains A list of domains this address belongs to. + GetPropertyDomains() ([]string, error) + + // GetPropertySearches A list of dns searches. + GetPropertySearches() ([]string, error) + + // GetPropertyDnsOptions A list of DNS options that modify the behavior of the DNS resolver. See resolv.conf(5) manual page for the list of supported options. + GetPropertyDnsOptions() ([]string, error) + + // GetPropertyDnsPriority The relative priority of DNS servers. + GetPropertyDnsPriority() (uint32, error) + + // GetPropertyWinsServerData The Windows Internet Name Service servers associated with the connection. + GetPropertyWinsServerData() ([]string, error) + + MarshalJSON() ([]byte, error) +} + +func NewIP4Config(objectPath dbus.ObjectPath) (IP4Config, error) { + var c ip4Config + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type ip4Config struct { + dbusBase +} + +// Deprecated: use GetPropertyAddressData +func (c *ip4Config) GetPropertyAddresses() ([]IP4Address, error) { + addresses, err := c.getSliceSliceUint32Property(IP4ConfigPropertyAddresses) + ret := make([]IP4Address, len(addresses)) + + if err != nil { + return ret, err + } + + for i, parts := range addresses { + ret[i] = IP4Address{ + Address: ip4ToString(parts[0]), + Prefix: uint8(parts[1]), + Gateway: ip4ToString(parts[2]), + } + } + + return ret, nil +} + +func (c *ip4Config) GetPropertyAddressData() ([]IP4AddressData, error) { + addresses, err := c.getSliceMapStringVariantProperty(IP4ConfigPropertyAddressData) + ret := make([]IP4AddressData, len(addresses)) + + if err != nil { + return ret, err + } + + for i, address := range addresses { + prefix, ok := address["prefix"].Value().(uint32) + if !ok { + return ret, errors.New("unexpected variant type for address prefix") + } + + address, ok := address["address"].Value().(string) + if !ok { + return ret, errors.New("unexpected variant type for address") + } + + ret[i] = IP4AddressData{ + Address: address, + Prefix: uint8(prefix), + } + } + + return ret, nil +} + +func (c *ip4Config) GetPropertyGateway() (string, error) { + return c.getStringProperty(IP4ConfigPropertyGateway) +} + +// Deprecated: use GetPropertyRouteData +func (c *ip4Config) GetPropertyRoutes() ([]IP4Route, error) { + routes, err := c.getSliceSliceUint32Property(IP4ConfigPropertyRoutes) + ret := make([]IP4Route, len(routes)) + + if err != nil { + return ret, err + } + + for i, parts := range routes { + ret[i] = IP4Route{ + Route: ip4ToString(parts[0]), + Prefix: uint8(parts[1]), + NextHop: ip4ToString(parts[2]), + Metric: uint8(parts[3]), + } + } + + return ret, nil +} + +func (c *ip4Config) GetPropertyRouteData() ([]IP4RouteData, error) { + routesData, err := c.getSliceMapStringVariantProperty(IP4ConfigPropertyRouteData) + routes := make([]IP4RouteData, len(routesData)) + + if err != nil { + return routes, err + } + + for index, routeData := range routesData { + + route := IP4RouteData{} + + for routeDataAttributeName, routeDataAttribute := range routeData { + switch routeDataAttributeName { + case "dest": + destination, ok := routeDataAttribute.Value().(string) + if !ok { + return routes, errors.New("unexpected variant type for dest") + } + route.Destination = destination + case "prefix": + prefix, ok := routeDataAttribute.Value().(uint32) + if !ok { + return routes, errors.New("unexpected variant type for prefix") + } + route.Prefix = uint8(prefix) + case "next-hop": + nextHop, ok := routeDataAttribute.Value().(string) + if !ok { + return routes, errors.New("unexpected variant type for next-hop") + } + route.NextHop = nextHop + case "metric": + metric, ok := routeDataAttribute.Value().(uint32) + if !ok { + return routes, errors.New("unexpected variant type for metric") + } + route.Metric = uint8(metric) + default: + if route.AdditionalAttributes == nil { + route.AdditionalAttributes = make(map[string]string) + } + route.AdditionalAttributes[routeDataAttributeName] = routeDataAttribute.String() + } + } + + routes[index] = route + } + return routes, nil +} + +// Deprecated: use GetPropertyNameserverData +func (c *ip4Config) GetPropertyNameservers() ([]string, error) { + nameservers, err := c.getSliceUint32Property(IP4ConfigPropertyNameservers) + ret := make([]string, len(nameservers)) + + if err != nil { + return ret, err + } + + for i, ns := range nameservers { + ret[i] = ip4ToString(ns) + } + + return ret, nil +} + +func (c *ip4Config) GetPropertyNameserverData() ([]IP4NameserverData, error) { + nameserversData, err := c.getSliceMapStringVariantProperty(IP4ConfigPropertyNameserverData) + nameservers := make([]IP4NameserverData, 0, len(nameserversData)) + + if err != nil { + return nameservers, err + } + + for _, nameserverData := range nameserversData { + address, ok := nameserverData["address"].Value().(string) + + if !ok { + return nameservers, errors.New("unexpected variant type for address") + } + + nameserver := IP4NameserverData{ + Address: address, + } + + nameservers = append(nameservers, nameserver) + } + return nameservers, nil +} + +func (c *ip4Config) GetPropertyDomains() ([]string, error) { + return c.getSliceStringProperty(IP4ConfigPropertyDomains) +} + +func (c *ip4Config) GetPropertySearches() ([]string, error) { + return c.getSliceStringProperty(IP4ConfigPropertySearches) +} + +func (c *ip4Config) GetPropertyDnsOptions() ([]string, error) { + return c.getSliceStringProperty(IP4ConfigPropertyDnsOptions) +} + +func (c *ip4Config) GetPropertyDnsPriority() (uint32, error) { + return c.getUint32Property(IP4ConfigPropertyDnsPriority) +} + +func (c *ip4Config) GetPropertyWinsServerData() ([]string, error) { + return c.getSliceStringProperty(IP4ConfigPropertyWinsServerData) +} + +func (c *ip4Config) MarshalJSON() ([]byte, error) { + Addresses, err := c.GetPropertyAddressData() + if err != nil { + return nil, err + } + Routes, err := c.GetPropertyRouteData() + if err != nil { + return nil, err + } + Nameservers, err := c.GetPropertyNameserverData() + if err != nil { + return nil, err + } + Domains, err := c.GetPropertyDomains() + if err != nil { + return nil, err + } + + return json.Marshal(map[string]interface{}{ + "Addresses": Addresses, + "Routes": Routes, + "Nameservers": Nameservers, + "Domains": Domains, + }) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/IP6Config.go b/vendor/github.com/Wifx/gonetworkmanager/v2/IP6Config.go new file mode 100644 index 0000000..4d4cb63 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/IP6Config.go @@ -0,0 +1,215 @@ +package gonetworkmanager + +import ( + "encoding/json" + "errors" + + "github.com/godbus/dbus/v5" +) + +const ( + IP6ConfigInterface = NetworkManagerInterface + ".IP6Config" + + /* Properties */ + IP6ConfigPropertyAddresses = IP6ConfigInterface + ".Addresses" // readable a(ayuay) + IP6ConfigPropertyAddressData = IP6ConfigInterface + ".AddressData" // readable aa{sv} + IP6ConfigPropertyGateway = IP6ConfigInterface + ".Gateway" // readable s + IP6ConfigPropertyRoutes = IP6ConfigInterface + ".Routes" // readable a(ayuayu) + IP6ConfigPropertyRouteData = IP6ConfigInterface + ".RouteData" // readable aa{sv} + IP6ConfigPropertyNameservers = IP6ConfigInterface + ".Nameservers" // readable aay + IP6ConfigPropertyDomains = IP6ConfigInterface + ".Domains" // readable as + IP6ConfigPropertySearches = IP6ConfigInterface + ".Searches" // readable as + IP6ConfigPropertyDnsOptions = IP6ConfigInterface + ".DnsOptions" // readable as + IP6ConfigPropertyDnsPriority = IP6ConfigInterface + ".DnsPriority" // readable i +) + +// Deprecated: use IP6AddressData instead +type IP6Address struct { + Address string + Prefix uint8 + Gateway string +} + +type IP6AddressData struct { + Address string + Prefix uint8 +} + +// Deprecated: use IP6RouteData instead +type IP6Route struct { + Route string + Prefix uint8 + NextHop string + Metric uint8 +} + +type IP6RouteData struct { + Destination string + Prefix uint8 + NextHop string + Metric uint8 + AdditionalAttributes map[string]string +} + +type IP6Config interface { + + // GetPropertyAddressData Array of IP address data objects. All addresses will include "address" (an IP address string), and "prefix" (a uint). Some addresses may include additional attributes. + GetPropertyAddressData() ([]IP6AddressData, error) + + // GetPropertyGateway The gateway in use. + GetPropertyGateway() (string, error) + + // GetPropertyRouteData Array of IP route data objects. All routes will include "dest" (an IP address string) and "prefix" (a uint). Some routes may include "next-hop" (an IP address string), "metric" (a uint), and additional attributes. + GetPropertyRouteData() ([]IP6RouteData, error) + + // GetPropertyNameservers GetNameservers gets the nameservers in use. + GetPropertyNameservers() ([][]byte, error) + + // GetPropertyDomains A list of domains this address belongs to. + GetPropertyDomains() ([]string, error) + + // GetPropertySearches A list of dns searches. + GetPropertySearches() ([]string, error) + + // GetPropertyDnsOptions A list of DNS options that modify the behavior of the DNS resolver. See resolv.conf(5) manual page for the list of supported options. + GetPropertyDnsOptions() ([]string, error) + + // GetPropertyDnsPriority The relative priority of DNS servers. + GetPropertyDnsPriority() (uint32, error) + + MarshalJSON() ([]byte, error) +} + +func NewIP6Config(objectPath dbus.ObjectPath) (IP6Config, error) { + var c ip6Config + return &c, c.init(NetworkManagerInterface, objectPath) +} + +type ip6Config struct { + dbusBase +} + +func (c *ip6Config) GetPropertyAddressData() ([]IP6AddressData, error) { + addresses, err := c.getSliceMapStringVariantProperty(IP6ConfigPropertyAddressData) + ret := make([]IP6AddressData, len(addresses)) + + if err != nil { + return ret, err + } + + for i, address := range addresses { + prefix, ok := address["prefix"].Value().(uint32) + if !ok { + return ret, errors.New("unexpected variant type for prefix") + } + + address, ok := address["address"].Value().(string) + if !ok { + return ret, errors.New("unexpected variant type for address") + } + + ret[i] = IP6AddressData{ + Address: address, + Prefix: uint8(prefix), + } + } + + return ret, nil +} + +func (c *ip6Config) GetPropertyGateway() (string, error) { + return c.getStringProperty(IP6ConfigPropertyGateway) +} + +func (c *ip6Config) GetPropertyRouteData() ([]IP6RouteData, error) { + routesData, err := c.getSliceMapStringVariantProperty(IP6ConfigPropertyRouteData) + routes := make([]IP6RouteData, len(routesData)) + + if err != nil { + return routes, err + } + + for index, routeData := range routesData { + + route := IP6RouteData{} + + for routeDataAttributeName, routeDataAttribute := range routeData { + switch routeDataAttributeName { + case "dest": + destination, ok := routeDataAttribute.Value().(string) + if !ok { + return routes, errors.New("unexpected variant type for dest") + } + route.Destination = destination + case "prefix": + prefix, ok := routeDataAttribute.Value().(uint32) + if !ok { + return routes, errors.New("unexpected variant type for prefix") + } + route.Prefix = uint8(prefix) + case "next-hop": + nextHop, ok := routeDataAttribute.Value().(string) + if !ok { + return routes, errors.New("unexpected variant type for next-hop") + } + route.NextHop = nextHop + case "metric": + metric, ok := routeDataAttribute.Value().(uint32) + if !ok { + return routes, errors.New("unexpected variant type for metric") + } + route.Metric = uint8(metric) + default: + if route.AdditionalAttributes == nil { + route.AdditionalAttributes = make(map[string]string) + } + route.AdditionalAttributes[routeDataAttributeName] = routeDataAttribute.String() + } + } + + routes[index] = route + } + return routes, nil +} + +func (c *ip6Config) GetPropertyNameservers() ([][]byte, error) { + nameservers, err := c.getSliceSliceByteProperty(IP6ConfigPropertyNameservers) + ret := make([][]byte, len(nameservers)) + + if err != nil { + return ret, err + } + + for i, nameserver := range nameservers { + ret[i] = nameserver + } + + return ret, nil +} + +func (c *ip6Config) GetPropertyDomains() ([]string, error) { + return c.getSliceStringProperty(IP6ConfigPropertyDomains) +} + +func (c *ip6Config) GetPropertySearches() ([]string, error) { + return c.getSliceStringProperty(IP6ConfigPropertySearches) +} + +func (c *ip6Config) GetPropertyDnsOptions() ([]string, error) { + return c.getSliceStringProperty(IP6ConfigPropertyDnsOptions) +} + +func (c *ip6Config) GetPropertyDnsPriority() (uint32, error) { + return c.getUint32Property(IP6ConfigPropertyDnsPriority) +} + +func (c *ip6Config) MarshalJSON() ([]byte, error) { + m := make(map[string]interface{}) + + m["Addresses"], _ = c.GetPropertyAddressData() + m["Routes"], _ = c.GetPropertyRouteData() + m["Nameservers"], _ = c.GetPropertyNameservers() + m["Domains"], _ = c.GetPropertyDomains() + + return json.Marshal(m) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/LICENSE b/vendor/github.com/Wifx/gonetworkmanager/v2/LICENSE new file mode 100644 index 0000000..8896b2c --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/LICENSE @@ -0,0 +1,45 @@ +The MIT License (MIT) + +Copyright (c) 2019 Wifx Sàrl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +------------------------------------------------------------------------------ + +The MIT License (MIT) + +Copyright (c) 2016 Bellerophon Mobile + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/NetworkManager.go b/vendor/github.com/Wifx/gonetworkmanager/v2/NetworkManager.go new file mode 100644 index 0000000..3dc19c3 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/NetworkManager.go @@ -0,0 +1,751 @@ +package gonetworkmanager + +import ( + "encoding/json" + + "github.com/godbus/dbus/v5" +) + +const ( + NetworkManagerInterface = "org.freedesktop.NetworkManager" + NetworkManagerObjectPath = "/org/freedesktop/NetworkManager" + + /* Methods */ + NetworkManagerReload = NetworkManagerInterface + ".Reload" + NetworkManagerGetDevices = NetworkManagerInterface + ".GetDevices" + NetworkManagerGetAllDevices = NetworkManagerInterface + ".GetAllDevices" + NetworkManagerGetDeviceByIpIface = NetworkManagerInterface + ".GetDeviceByIpIface" + NetworkManagerActivateConnection = NetworkManagerInterface + ".ActivateConnection" + NetworkManagerAddAndActivateConnection = NetworkManagerInterface + ".AddAndActivateConnection" + NetworkManagerAddAndActivateConnection2 = NetworkManagerInterface + ".AddAndActivateConnection2" + NetworkManagerDeactivateConnection = NetworkManagerInterface + ".DeactivateConnection" + NetworkManagerSleep = NetworkManagerInterface + ".Sleep" + NetworkManagerEnable = NetworkManagerInterface + ".Enable" + NetworkManagerGetPermissions = NetworkManagerInterface + ".GetPermissions" + NetworkManagerSetLogging = NetworkManagerInterface + ".SetLogging" + NetworkManagerGetLogging = NetworkManagerInterface + ".GetLogging" + NetworkManagerCheckConnectivity = NetworkManagerInterface + ".CheckConnectivity" + NetworkManagerState = NetworkManagerInterface + ".state" + NetworkManagerCheckpointCreate = NetworkManagerInterface + ".CheckpointCreate" + NetworkManagerCheckpointDestroy = NetworkManagerInterface + ".CheckpointDestroy" + NetworkManagerCheckpointRollback = NetworkManagerInterface + ".CheckpointRollback" + NetworkManagerCheckpointAdjustRollbackTimeout = NetworkManagerInterface + ".CheckpointAdjustRollbackTimeout" + + /* Property */ + NetworkManagerPropertyDevices = NetworkManagerInterface + ".Devices" // readable ao + NetworkManagerPropertyAllDevices = NetworkManagerInterface + ".AllDevices" // readable ao + NetworkManagerPropertyCheckpoints = NetworkManagerInterface + ".Checkpoints" // readable ao + NetworkManagerPropertyNetworkingEnabled = NetworkManagerInterface + ".NetworkingEnabled" // readable b + NetworkManagerPropertyWirelessEnabled = NetworkManagerInterface + ".WirelessEnabled" // readwrite b + NetworkManagerPropertyWirelessHardwareEnabled = NetworkManagerInterface + ".WirelessHardwareEnabled" // readable b + NetworkManagerPropertyWwanEnabled = NetworkManagerInterface + ".WwanEnabled" // readwrite b + NetworkManagerPropertyWwanHardwareEnabled = NetworkManagerInterface + ".WwanHardwareEnabled" // readable b + NetworkManagerPropertyWimaxEnabled = NetworkManagerInterface + ".WimaxEnabled" // readwrite b + NetworkManagerPropertyWimaxHardwareEnabled = NetworkManagerInterface + ".WimaxHardwareEnabled" // readable b + NetworkManagerPropertyActiveConnections = NetworkManagerInterface + ".ActiveConnections" // readable ao + NetworkManagerPropertyPrimaryConnection = NetworkManagerInterface + ".PrimaryConnection" // readable o + NetworkManagerPropertyPrimaryConnectionType = NetworkManagerInterface + ".PrimaryConnectionType" // readable s + NetworkManagerPropertyMetered = NetworkManagerInterface + ".Metered" // readable u + NetworkManagerPropertyActivatingConnection = NetworkManagerInterface + ".ActivatingConnection" // readable o + NetworkManagerPropertyStartup = NetworkManagerInterface + ".Startup" // readable b + NetworkManagerPropertyVersion = NetworkManagerInterface + ".Version" // readable s + NetworkManagerPropertyCapabilities = NetworkManagerInterface + ".Capabilities" // readable au + NetworkManagerPropertyState = NetworkManagerInterface + ".State" // readable u + NetworkManagerPropertyConnectivity = NetworkManagerInterface + ".Connectivity" // readable u + NetworkManagerPropertyConnectivityCheckAvailable = NetworkManagerInterface + ".ConnectivityCheckAvailable" // readable b + NetworkManagerPropertyConnectivityCheckEnabled = NetworkManagerInterface + ".ConnectivityCheckEnabled" // readwrite b + NetworkManagerPropertyGlobalDnsConfiguration = NetworkManagerInterface + ".GlobalDnsConfiguration" // readwrite a{sv} +) + +type NetworkManager interface { + /* METHODS */ + + // Reload NetworkManager's configuration and perform certain updates, like flushing a cache or rewriting external state to disk. This is similar to sending SIGHUP to NetworkManager but it allows for more fine-grained control over what to reload (see flags). It also allows non-root access via PolicyKit and contrary to signals it is synchronous. + // No flags (0x00) means to reload everything that is supported which is identical to sending a SIGHUP. + // (0x01) means to reload the NetworkManager.conf configuration from disk. Note that this does not include connections, which can be reloaded via Setting's ReloadConnections. + // (0x02) means to update DNS configuration, which usually involves writing /etc/resolv.conf anew. + // (0x04) means to restart the DNS plugin. This is for example useful when using dnsmasq plugin, which uses additional configuration in /etc/NetworkManager/dnsmasq.d. If you edit those files, you can restart the DNS plugin. This action shortly interrupts name resolution. Note that flags may affect each other. For example, restarting the DNS plugin (0x04) implicitly updates DNS too (0x02). Or when reloading the configuration (0x01), changes to DNS setting also cause a DNS update (0x02). However, (0x01) does not involve restarting the DNS plugin (0x04) or update resolv.conf (0x02), unless the DNS related configuration changes in NetworkManager.conf. + Reload(flags uint32) error + + // GetDevices Get the list of realized network devices. + GetDevices() ([]Device, error) + + // GetAllDevices Get the list of all network devices. + GetAllDevices() ([]Device, error) + + // GetDeviceByIpIface Return the object path of the network device referenced by its IP interface name. Note that some devices (usually modems) only have an IP interface name when they are connected. + GetDeviceByIpIface(interfaceId string) (Device, error) + + // ActivateConnection Activate a connection using the supplied device. + ActivateConnection(connection Connection, device Device, specificObject *dbus.Object) (ActiveConnection, error) + + // AddAndActivateConnection Adds a new connection using the given details (if any) as a template (automatically filling in missing settings with the capabilities of the given device), then activate the new connection. Cannot be used for VPN connections at this time. + AddAndActivateConnection(connection map[string]map[string]interface{}, device Device) (ActiveConnection, error) + + // ActivateWirelessConnection requests activating access point to network device + ActivateWirelessConnection(connection Connection, device Device, accessPoint AccessPoint) (ActiveConnection, error) + + // AddAndActivateWirelessConnection adds a new connection profile to the network device it has been + // passed. It then activates the connection to the passed access point. The first parameter contains + // additional information for the connection (most probably the credentials). + // Example contents for connection are: + // connection := make(map[string]map[string]interface{}) + // connection["802-11-wireless"] = make(map[string]interface{}) + // connection["802-11-wireless"]["security"] = "802-11-wireless-security" + // connection["802-11-wireless-security"] = make(map[string]interface{}) + // connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk" + // connection["802-11-wireless-security"]["psk"] = password + AddAndActivateWirelessConnection(connection map[string]map[string]interface{}, device Device, accessPoint AccessPoint) (ActiveConnection, error) + + // DeactivateConnection Deactivate an active connection. + DeactivateConnection(connection ActiveConnection) error + + // Sleep Control the NetworkManager daemon's sleep state. When asleep, all interfaces that it manages are deactivated. When awake, devices are available to be activated. This command should not be called directly by users or clients; it is intended for system suspend/resume tracking. + // sleepnWake: Indicates whether the NetworkManager daemon should sleep or wake. + Sleep(sleepNWake bool) error + + // Enable Control whether overall networking is enabled or disabled. When disabled, all interfaces that NM manages are deactivated. When enabled, all managed interfaces are re-enabled and available to be activated. This command should be used by clients that provide to users the ability to enable/disable all networking. + // enableNDisable: If FALSE, indicates that all networking should be disabled. If TRUE, indicates that NetworkManager should begin managing network devices. + Enable(enableNDisable bool) error + + // CheckConnectivity Re-check the network connectivity state. + CheckConnectivity() error + + // State The overall networking state as determined by the NetworkManager daemon, based on the state of network devices under its management. + State() (NmState, error) + + // CheckpointCreate Create a checkpoint of the current networking configuration for given interfaces. If rollback_timeout is not zero, a rollback is automatically performed after the given timeout. + // devices: A list of device paths for which a checkpoint should be created. An empty list means all devices. + // rollbackTimeout: The time in seconds until NetworkManager will automatically rollback to the checkpoint. Set to zero for infinite. + // flags: Flags for the creation. + // returns: On success, the new checkpoint. + CheckpointCreate(devices []Device, rollbackTimeout uint32, flags uint32) (Checkpoint, error) + + // CheckpointDestroy Destroy a previously created checkpoint. + // checkpoint: The checkpoint to be destroyed. Set to empty to cancel all pending checkpoints. + CheckpointDestroy(checkpoint Checkpoint) error + + // CheckpointRollback Rollback a checkpoint before the timeout is reached. + // checkpoint: The checkpoint to be rolled back. + // result: On return, a dictionary of devices and results. Devices are represented by their original D-Bus path; each result is a RollbackResult. + CheckpointRollback(checkpoint Checkpoint) (result map[dbus.ObjectPath]NmRollbackResult, err error) + + // CheckpointAdjustRollbackTimeout Reset the timeout for rollback for the checkpoint. + // Since: 1.12 + // addTimeout: number of seconds from ~now~ in which the timeout will expire. Set to 0 to disable the timeout. Note that the added seconds start counting from now, not "Created" timestamp or the previous expiration time. Note that the "Created" property of the checkpoint will stay unchanged by this call. However, the "RollbackTimeout" will be recalculated to give the approximate new expiration time. The new "RollbackTimeout" property will be approximate up to one second precision, which is the accuracy of the property. + CheckpointAdjustRollbackTimeout(checkpoint Checkpoint, addTimeout uint32) error + + /* PROPERTIES */ + + // GetPropertyDevices The list of realized network devices. Realized devices are those which have backing resources (eg from the kernel or a management daemon like ModemManager, teamd, etc). + GetPropertyDevices() ([]Device, error) + + // GetPropertyAllDevices The list of both realized and un-realized network devices. Un-realized devices are software devices which do not yet have backing resources, but for which backing resources can be created if the device is activated. + GetPropertyAllDevices() ([]Device, error) + + // GetPropertyCheckpoints The list of active checkpoints. + GetPropertyCheckpoints() ([]Checkpoint, error) + + // GetPropertyNetworkingEnabled Indicates if overall networking is currently enabled or not. See the Enable() method. + GetPropertyNetworkingEnabled() (bool, error) + + // GetPropertyWirelessEnabled Indicates if wireless is currently enabled or not. + GetPropertyWirelessEnabled() (bool, error) + SetPropertyWirelessEnabled(bool) error + + // GetPropertyWirelessHardwareEnabled Indicates if the wireless hardware is currently enabled, i.e. the state of the RF kill switch. + GetPropertyWirelessHardwareEnabled() (bool, error) + + // GetPropertyWwanEnabled Indicates if mobile broadband devices are currently enabled or not. + GetPropertyWwanEnabled() (bool, error) + + // GetPropertyWwanHardwareEnabled Indicates if the mobile broadband hardware is currently enabled, i.e. the state of the RF kill switch. + GetPropertyWwanHardwareEnabled() (bool, error) + + // GetPropertyWimaxEnabled Indicates if WiMAX devices are currently enabled or not. + GetPropertyWimaxEnabled() (bool, error) + + // GetPropertyWimaxHardwareEnabled Indicates if the WiMAX hardware is currently enabled, i.e. the state of the RF kill switch. + GetPropertyWimaxHardwareEnabled() (bool, error) + + // GetPropertyActiveConnections List of active connection object paths. + GetPropertyActiveConnections() ([]ActiveConnection, error) + + // GetPropertyPrimaryConnection The object path of the "primary" active connection being used to access the network. In particular, if there is no VPN active, or the VPN does not have the default route, then this indicates the connection that has the default route. If there is a VPN active with the default route, then this indicates the connection that contains the route to the VPN endpoint. + GetPropertyPrimaryConnection() (ActiveConnection, error) + + // GetPropertyPrimaryConnectionType The connection type of the "primary" active connection being used to access the network. This is the same as the Type property on the object indicated by PrimaryConnection. + GetPropertyPrimaryConnectionType() (string, error) + + // GetPropertyMetered Indicates whether the connectivity is metered. This is equivalent to the metered property of the device associated with the primary connection. + GetPropertyMetered() (NmMetered, error) + + // GetPropertyActivatingConnection The object path of an active connection that is currently being activated and which is expected to become the new PrimaryConnection when it finishes activating. + GetPropertyActivatingConnection() (ActiveConnection, error) + + // GetPropertyStartup Indicates whether NM is still starting up; this becomes FALSE when NM has finished attempting to activate every connection that it might be able to activate at startup. + GetPropertyStartup() (bool, error) + + // GetPropertyVersion NetworkManager version. + GetPropertyVersion() (string, error) + + // GetPropertyCapabilities The current set of capabilities. See NMCapability for currently defined capability numbers. The array is guaranteed to be sorted in ascending order without duplicates. + GetPropertyCapabilities() ([]NmCapability, error) + + // GetPropertyState The overall state of the NetworkManager daemon. + // This takes state of all active connections and the connectivity state into account to produce a single indicator of the network accessibility status. + // The graphical shells may use this property to provide network connection status indication and applications may use this to check if Internet connection is accessible. Shell that is able to cope with captive portals should use the "Connectivity" property to decide whether to present a captive portal authentication dialog. + GetPropertyState() (NmState, error) + + // GetPropertyConnectivity The result of the last connectivity check. The connectivity check is triggered automatically when a default connection becomes available, periodically and by calling a CheckConnectivity() method. + // This property is in general useful for the graphical shell to determine whether the Internet access is being hijacked by an authentication gateway (a "captive portal"). In such case it would typically present a web browser window to give the user a chance to authenticate and call CheckConnectivity() when the user submits a form or dismisses the window. + // To determine the whether the user is able to access the Internet without dealing with captive portals (e.g. to provide a network connection indicator or disable controls that require Internet access), the "State" property is more suitable. + GetPropertyConnectivity() (NmConnectivity, error) + + // GetPropertyConnectivityCheckAvailable Indicates whether connectivity checking service has been configured. This may return true even if the service is not currently enabled. + // This is primarily intended for use in a privacy control panel, as a way to determine whether to show an option to enable/disable the feature. + GetPropertyConnectivityCheckAvailable() (bool, error) + + // GetPropertyConnectivityCheckEnabled Indicates whether connectivity checking is enabled. This property can also be written to to disable connectivity checking (as a privacy control panel might want to do). + GetPropertyConnectivityCheckEnabled() (bool, error) + + // Dictionary of global DNS settings where the key is one of "searches", "options" and "domains". The values for the "searches" and "options" keys are string arrays describing the list of search domains and resolver options, respectively. The value of the "domains" key is a second-level dictionary, where each key is a domain name, and each key's value is a third-level dictionary with the keys "servers" and "options". "servers" is a string array of DNS servers, "options" is a string array of domain-specific options. + //GetPropertyGlobalDnsConfiguration() []interface{} + + Subscribe() <-chan *dbus.Signal + Unsubscribe() + + MarshalJSON() ([]byte, error) +} + +func NewNetworkManager() (NetworkManager, error) { + var nm networkManager + return &nm, nm.init(NetworkManagerInterface, NetworkManagerObjectPath) +} + +type networkManager struct { + dbusBase + + sigChan chan *dbus.Signal +} + +func (nm *networkManager) Reload(flags uint32) error { + return nm.call(NetworkManagerReload, flags) +} + +func (nm *networkManager) GetDevices() (devices []Device, err error) { + var devicePaths []dbus.ObjectPath + err = nm.callWithReturn(&devicePaths, NetworkManagerGetDevices) + if err != nil { + return + } + + devices = make([]Device, len(devicePaths)) + + for i, path := range devicePaths { + devices[i], err = DeviceFactory(path) + if err != nil { + return + } + } + + return +} + +func (nm *networkManager) GetAllDevices() (devices []Device, err error) { + var devicePaths []dbus.ObjectPath + + err = nm.callWithReturn(&devicePaths, NetworkManagerGetAllDevices) + if err != nil { + return + } + + devices = make([]Device, len(devicePaths)) + + for i, path := range devicePaths { + devices[i], err = DeviceFactory(path) + if err != nil { + return + } + } + + return +} + +func (nm *networkManager) GetDeviceByIpIface(interfaceId string) (device Device, err error) { + var devicePath dbus.ObjectPath + + err = nm.callWithReturn(&devicePath, NetworkManagerGetDeviceByIpIface, interfaceId) + if err != nil { + return + } + + device, err = DeviceFactory(devicePath) + if err != nil { + return + } + + return +} + +func (nm *networkManager) ActivateConnection(connection Connection, device Device, specificObject *dbus.Object) (ac ActiveConnection, err error) { + var connectionPath dbus.ObjectPath + + var devicePath dbus.ObjectPath + if device != nil { + devicePath = device.GetPath() + } else { + devicePath = "/" + } + + var specificObjectPath dbus.ObjectPath + if specificObject != nil { + specificObjectPath = specificObject.Path() + } else { + specificObjectPath = "/" + } + + err = nm.callWithReturn(&connectionPath, NetworkManagerActivateConnection, connection.GetPath(), devicePath, specificObjectPath) + if err != nil { + return + } + + ac, err = NewActiveConnection(connectionPath) + if err != nil { + return + } + + return +} + +func (nm *networkManager) AddAndActivateConnection(connection map[string]map[string]interface{}, d Device) (ac ActiveConnection, err error) { + var opath1 dbus.ObjectPath + var opath2 dbus.ObjectPath + + var devicePath dbus.ObjectPath + if d != nil { + devicePath = d.GetPath() + } + + err = nm.callWithReturn2(&opath1, &opath2, NetworkManagerAddAndActivateConnection, connection, devicePath, dbus.ObjectPath("/")) + if err != nil { + return + } + + ac, err = NewActiveConnection(opath2) + if err != nil { + return + } + + return +} + +func (nm *networkManager) ActivateWirelessConnection(c Connection, d Device, ap AccessPoint) (ac ActiveConnection, err error) { + var opath dbus.ObjectPath + err = nm.callWithReturn(&opath, NetworkManagerActivateConnection, c.GetPath(), d.GetPath(), ap.GetPath()) + if err != nil { + return nil, err + } + + ac, err = NewActiveConnection(opath) + if err != nil { + return nil, err + } + + return +} + +func (nm *networkManager) AddAndActivateWirelessConnection(connection map[string]map[string]interface{}, d Device, ap AccessPoint) (ac ActiveConnection, err error) { + var opath1 dbus.ObjectPath + var opath2 dbus.ObjectPath + + err = nm.callWithReturn2(&opath1, &opath2, NetworkManagerAddAndActivateConnection, connection, d.GetPath(), ap.GetPath()) + if err != nil { + return + } + + ac, err = NewActiveConnection(opath2) + if err != nil { + return + } + return +} + +func (nm *networkManager) DeactivateConnection(c ActiveConnection) error { + return nm.call(NetworkManagerDeactivateConnection, c.GetPath()) +} + +func (nm *networkManager) Sleep(sleepNWake bool) error { + return nm.call(NetworkManagerSleep, sleepNWake) +} + +func (nm *networkManager) Enable(enableNDisable bool) error { + return nm.call(NetworkManagerEnable, enableNDisable) +} + +func (nm *networkManager) CheckConnectivity() error { + return nm.call(NetworkManagerCheckConnectivity) +} + +func (nm *networkManager) State() (state NmState, err error) { + err = nm.callWithReturn(&state, NetworkManagerState) + return +} + +func (nm *networkManager) CheckpointCreate(devices []Device, rollbackTimeout uint32, flags uint32) (cp Checkpoint, err error) { + + var devicePaths []dbus.ObjectPath + if len(devices) > 0 { + for _, device := range devices { + devicePaths = append(devicePaths, device.GetPath()) + } + } + + var checkpointPath dbus.ObjectPath + err = nm.callWithReturn(&checkpointPath, NetworkManagerCheckpointCreate, devicePaths, rollbackTimeout, flags) + if err != nil { + return + } + + cp, err = NewCheckpoint(checkpointPath) + return +} + +func (nm *networkManager) CheckpointDestroy(checkpoint Checkpoint) error { + if checkpoint == nil { + return nm.call(NetworkManagerCheckpointDestroy) + } else { + return nm.call(NetworkManagerCheckpointDestroy, checkpoint.GetPath()) + } +} + +func (nm *networkManager) CheckpointRollback(checkpoint Checkpoint) (results map[dbus.ObjectPath]NmRollbackResult, err error) { + + var ret map[dbus.ObjectPath]NmRollbackResult + + err = nm.callWithReturn(&ret, NetworkManagerCheckpointRollback, checkpoint.GetPath()) + if err != nil { + return + } + + results = map[dbus.ObjectPath]NmRollbackResult{} + for devicePath, result := range ret { + results[devicePath] = result + } + + return +} + +func (nm *networkManager) CheckpointAdjustRollbackTimeout(checkpoint Checkpoint, addTimeout uint32) error { + return nm.call(NetworkManagerCheckpointAdjustRollbackTimeout, checkpoint, addTimeout) +} + +/* PROPERTIES */ + +func (nm *networkManager) GetPropertyDevices() ([]Device, error) { + devicesPaths, err := nm.getSliceObjectProperty(NetworkManagerPropertyDevices) + if err != nil { + return nil, err + } + + devices := make([]Device, len(devicesPaths)) + for i, path := range devicesPaths { + devices[i], err = NewDevice(path) + if err != nil { + return devices, err + } + } + + return devices, nil +} + +func (nm *networkManager) GetPropertyAllDevices() ([]Device, error) { + devicesPaths, err := nm.getSliceObjectProperty(NetworkManagerPropertyAllDevices) + if err != nil { + return nil, err + } + + devices := make([]Device, len(devicesPaths)) + for i, path := range devicesPaths { + devices[i], err = NewDevice(path) + if err != nil { + return devices, err + } + } + + return devices, nil +} + +func (nm *networkManager) GetPropertyCheckpoints() ([]Checkpoint, error) { + checkpointsPaths, err := nm.getSliceObjectProperty(NetworkManagerPropertyCheckpoints) + if err != nil { + return nil, err + } + + checkpoints := make([]Checkpoint, len(checkpointsPaths)) + for i, path := range checkpointsPaths { + checkpoints[i], err = NewCheckpoint(path) + if err != nil { + return checkpoints, err + } + } + + return checkpoints, nil +} + +func (nm *networkManager) GetPropertyNetworkingEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyNetworkingEnabled) +} + +func (nm *networkManager) GetPropertyWirelessEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWirelessEnabled) +} + +func (nm *networkManager) SetPropertyWirelessEnabled(enabled bool) error { + return nm.setProperty(NetworkManagerPropertyWirelessEnabled, enabled) +} + +func (nm *networkManager) GetPropertyWirelessHardwareEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWirelessHardwareEnabled) +} + +func (nm *networkManager) GetPropertyWwanEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWwanEnabled) +} + +func (nm *networkManager) GetPropertyWwanHardwareEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWwanHardwareEnabled) +} + +func (nm *networkManager) GetPropertyWimaxEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWimaxEnabled) +} + +func (nm *networkManager) GetPropertyWimaxHardwareEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyWimaxHardwareEnabled) +} + +func (nm *networkManager) GetPropertyActiveConnections() ([]ActiveConnection, error) { + acPaths, err := nm.getSliceObjectProperty(NetworkManagerPropertyActiveConnections) + if err != nil { + return nil, err + } + + ac := make([]ActiveConnection, len(acPaths)) + for i, path := range acPaths { + ac[i], err = NewActiveConnection(path) + if err != nil { + return ac, err + } + } + + return ac, nil +} + +func (nm *networkManager) GetPropertyPrimaryConnection() (ActiveConnection, error) { + activeConnectionPath, err := nm.getObjectProperty(NetworkManagerPropertyPrimaryConnection) + + if err != nil { + return nil, err + } + + return NewActiveConnection(activeConnectionPath) +} + +func (nm *networkManager) GetPropertyPrimaryConnectionType() (string, error) { + return nm.getStringProperty(NetworkManagerPropertyPrimaryConnectionType) +} + +func (nm *networkManager) GetPropertyMetered() (NmMetered, error) { + v, err := nm.getUint32Property(NetworkManagerPropertyMetered) + return NmMetered(v), err +} + +func (nm *networkManager) GetPropertyActivatingConnection() (ActiveConnection, error) { + panic("implement me") +} + +func (nm *networkManager) GetPropertyStartup() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyStartup) +} + +func (nm *networkManager) GetPropertyVersion() (string, error) { + return nm.getStringProperty(NetworkManagerPropertyVersion) +} + +func (nm *networkManager) GetPropertyCapabilities() ([]NmCapability, error) { + panic("implement me") +} + +func (nm *networkManager) GetPropertyState() (NmState, error) { + v, err := nm.getUint32Property(NetworkManagerPropertyState) + return NmState(v), err +} + +func (nm *networkManager) GetPropertyConnectivity() (NmConnectivity, error) { + v, err := nm.getUint32Property(NetworkManagerPropertyConnectivity) + return NmConnectivity(v), err +} + +func (nm *networkManager) GetPropertyConnectivityCheckAvailable() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyConnectivityCheckAvailable) +} + +func (nm *networkManager) GetPropertyConnectivityCheckEnabled() (bool, error) { + return nm.getBoolProperty(NetworkManagerPropertyConnectivityCheckEnabled) +} + +func (nm *networkManager) Subscribe() <-chan *dbus.Signal { + if nm.sigChan != nil { + return nm.sigChan + } + + nm.subscribeNamespace(NetworkManagerObjectPath) + nm.sigChan = make(chan *dbus.Signal, 10) + nm.conn.Signal(nm.sigChan) + + return nm.sigChan +} + +func (nm *networkManager) Unsubscribe() { + nm.conn.RemoveSignal(nm.sigChan) + nm.sigChan = nil +} + +func (nm *networkManager) MarshalJSON() ([]byte, error) { + + Devices, err := nm.GetPropertyDevices() + if err != nil { + return nil, err + } + + AllDevices, err := nm.GetPropertyAllDevices() + if err != nil { + return nil, err + } + + Checkpoints, err := nm.GetPropertyCheckpoints() + if err != nil { + return nil, err + } + + NetworkingEnabled, err := nm.GetPropertyNetworkingEnabled() + if err != nil { + return nil, err + } + + WirelessEnabled, err := nm.GetPropertyWirelessEnabled() + if err != nil { + return nil, err + } + + WirelessHardwareEnabled, err := nm.GetPropertyWirelessHardwareEnabled() + if err != nil { + return nil, err + } + + WwanEnabled, err := nm.GetPropertyWwanEnabled() + if err != nil { + return nil, err + } + + WwanHardwareEnabled, err := nm.GetPropertyWwanHardwareEnabled() + if err != nil { + return nil, err + } + + WimaxEnabled, err := nm.GetPropertyWimaxEnabled() + if err != nil { + return nil, err + } + + WimaxHardwareEnabled, err := nm.GetPropertyWimaxHardwareEnabled() + if err != nil { + return nil, err + } + + ActiveConnections, err := nm.GetPropertyActiveConnections() + if err != nil { + return nil, err + } + + PrimaryConnection, err := nm.GetPropertyPrimaryConnection() + if err != nil { + return nil, err + } + + PrimaryConnectionType, err := nm.GetPropertyPrimaryConnectionType() + if err != nil { + return nil, err + } + + Metered, err := nm.GetPropertyMetered() + if err != nil { + return nil, err + } + + ActivatingConnection, err := nm.GetPropertyActivatingConnection() + if err != nil { + return nil, err + } + + Startup, err := nm.GetPropertyStartup() + if err != nil { + return nil, err + } + + Version, err := nm.GetPropertyVersion() + if err != nil { + return nil, err + } + + Capabilities, err := nm.GetPropertyCapabilities() + if err != nil { + return nil, err + } + + State, err := nm.GetPropertyState() + if err != nil { + return nil, err + } + + Connectivity, err := nm.GetPropertyConnectivity() + if err != nil { + return nil, err + } + + ConnectivityCheckAvailable, err := nm.GetPropertyConnectivityCheckAvailable() + if err != nil { + return nil, err + } + + ConnectivityCheckEnabled, err := nm.GetPropertyConnectivityCheckEnabled() + if err != nil { + return nil, err + } + + return json.Marshal(map[string]interface{}{ + "Devices": Devices, + "AllDevices": AllDevices, + "Checkpoints": Checkpoints, + "NetworkingEnabled": NetworkingEnabled, + "WirelessEnabled": WirelessEnabled, + "WirelessHardwareEnabled": WirelessHardwareEnabled, + "WwanEnabled": WwanEnabled, + "WwanHardwareEnabled": WwanHardwareEnabled, + "WimaxEnabled": WimaxEnabled, + "WimaxHardwareEnabled": WimaxHardwareEnabled, + "ActiveConnections": ActiveConnections, + "PrimaryConnection": PrimaryConnection, + "PrimaryConnectionType": PrimaryConnectionType, + "Metered": Metered, + "ActivatingConnection": ActivatingConnection, + "Startup": Startup, + "Version": Version, + "Capabilities": Capabilities, + "State": State, + "Connectivity": Connectivity, + "ConnectivityCheckAvailable": ConnectivityCheckAvailable, + "ConnectivityCheckEnabled": ConnectivityCheckEnabled, + }) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/README.md b/vendor/github.com/Wifx/gonetworkmanager/v2/README.md new file mode 100644 index 0000000..7437990 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/README.md @@ -0,0 +1,35 @@ +[![GoDoc](https://godoc.org/github.com/Wifx/gonetworkmanager?status.svg)](https://pkg.go.dev/github.com/Wifx/gonetworkmanager) +[![Go build](https://github.com/Wifx/gonetworkmanager/workflows/Go/badge.svg)](https://github.com/Wifx/gonetworkmanager/actions?query=workflow%3AGo) + +gonetworkmanager +================ + +Go D-Bus bindings for [NetworkManager](https://networkmanager.dev/). + +## Usage + +You can find some examples in the [examples](examples) directory. + +## External documentations + +- [NetworkManager D-Bus Spec](https://networkmanager.dev/docs/api/latest/spec.html) +- [nm-settings-dbus](https://networkmanager.dev/docs/api/latest/nm-settings-dbus.html) + + +## Backward compatibility + +The library is most likely compatible with NetworkManager 0.9 to 1.40. + +## Tests + +Tested with NetworkManager 1.40.0. + +There are no automated tests for this library. Tests are made manually on a best-effort basis. Unit tests PRs are welcome. + +## Development and contributions + +There is no active development workforce from the maintainer. PRs are welcome. + +## Issues + +Before reporting an issue, please test the scenario with nmcli (if possible) to ensure the problem comes from the library. diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/Settings.go b/vendor/github.com/Wifx/gonetworkmanager/v2/Settings.go new file mode 100644 index 0000000..7b4f009 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/Settings.go @@ -0,0 +1,129 @@ +package gonetworkmanager + +import ( + "github.com/godbus/dbus/v5" +) + +const ( + SettingsInterface = NetworkManagerInterface + ".Settings" + SettingsObjectPath = NetworkManagerObjectPath + "/Settings" + + /* Methods */ + SettingsListConnections = SettingsInterface + ".ListConnections" + SettingsGetConnectionByUUID = SettingsInterface + ".GetConnectionByUuid" + SettingsAddConnection = SettingsInterface + ".AddConnection" + SettingsAddConnectionUnsaved = SettingsInterface + ".AddConnectionUnsaved" + SettingsLoadConnections = SettingsInterface + ".LoadConnections" + SettingsReloadConnections = SettingsInterface + ".ReloadConnections" + SettingsSaveHostname = SettingsInterface + ".SaveHostname" + + /* Properties */ + SettingsPropertyConnections = SettingsInterface + ".Connections" // readable ao + SettingsPropertyHostname = SettingsInterface + ".Hostname" // readable s + SettingsPropertyCanModify = SettingsInterface + ".CanModify" // readable b +) + +type Settings interface { + // ListConnections gets list the saved network connections known to NetworkManager + ListConnections() ([]Connection, error) + + // ReloadConnections tells NetworkManager to reload all connection files from disk, including noticing any added or deleted connection files. + ReloadConnections() error + + // GetConnectionByUUID gets the connection, given that connection's UUID. + GetConnectionByUUID(uuid string) (Connection, error) + + // AddConnection adds new connection and save it to disk. + AddConnection(settings ConnectionSettings) (Connection, error) + + // AddConnectionUnsaved Add new connection but do not save it to disk immediately. This operation does not start the network connection unless (1) device is idle and able to connect to the network described by the new connection, and (2) the connection is allowed to be started automatically. Use the 'Save' method on the connection to save these changes to disk. Note that unsaved changes will be lost if the connection is reloaded from disk (either automatically on file change or due to an explicit ReloadConnections call). + AddConnectionUnsaved(settings ConnectionSettings) (Connection, error) + + // SaveHostname Save the hostname to persistent configuration. + SaveHostname(hostname string) error + + // GetPropertyCanModify If true, adding and modifying connections is supported. + GetPropertyCanModify() (bool, error) + + // GetPropertyHostname The machine hostname stored in persistent configuration. + GetPropertyHostname() (string, error) +} + +func NewSettings() (Settings, error) { + var s settings + return &s, s.init(NetworkManagerInterface, SettingsObjectPath) +} + +type settings struct { + dbusBase +} + +func (s *settings) ListConnections() ([]Connection, error) { + var connectionPaths []dbus.ObjectPath + + err := s.callWithReturn(&connectionPaths, SettingsListConnections) + if err != nil { + return nil, err + } + + connections := make([]Connection, len(connectionPaths)) + + for i, path := range connectionPaths { + connections[i], err = NewConnection(path) + if err != nil { + return connections, err + } + } + + return connections, nil +} + +// ReloadConnections tells NetworkManager to reload (and apply) configuration files +// from disk taking notice of any added or removed connections. +func (s *settings) ReloadConnections() error { + return s.call(SettingsReloadConnections) +} + +// GetConnectionByUUID gets the connection, given that connection's UUID. +func (s *settings) GetConnectionByUUID(uuid string) (Connection, error) { + var path dbus.ObjectPath + err := s.callWithReturn(&path, SettingsGetConnectionByUUID, uuid) + if err != nil { + return nil, err + } + + return NewConnection(path) +} + +func (s *settings) AddConnection(settings ConnectionSettings) (Connection, error) { + var path dbus.ObjectPath + err := s.callWithReturn(&path, SettingsAddConnection, settings) + if err != nil { + return nil, err + } + + return NewConnection(path) +} + +func (s *settings) AddConnectionUnsaved(settings ConnectionSettings) (Connection, error) { + var path dbus.ObjectPath + err := s.callWithReturn(&path, SettingsAddConnectionUnsaved, settings) + + if err != nil { + return nil, err + } + + return NewConnection(path) +} + +func (s *settings) SaveHostname(hostname string) error { + return s.call(SettingsSaveHostname, hostname) +} + +func (s *settings) GetPropertyHostname() (string, error) { + return s.getStringProperty(SettingsPropertyHostname) +} + +func (s *settings) GetPropertyCanModify() (bool, error) { + return s.getBoolProperty(SettingsPropertyCanModify) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/VpnConnection.go b/vendor/github.com/Wifx/gonetworkmanager/v2/VpnConnection.go new file mode 100644 index 0000000..40cb155 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/VpnConnection.go @@ -0,0 +1,45 @@ +package gonetworkmanager + +import ( + "github.com/godbus/dbus/v5" +) + +const ( + VpnConnectionInterface = NetworkManagerInterface + ".VPN.Connection" + + /* Properties */ + VpnConnectionPropertyVpnState = VpnConnectionInterface + ".VpnState" // readable u + VpnConnectionPropertyBanner = VpnConnectionInterface + ".Banner" // readable s +) + +type VpnConnection interface { + GetPath() dbus.ObjectPath + + // GetPropertyVpnState The VPN-specific state of the connection. + GetPropertyVpnState() (NmVpnConnectionState, error) + + // GetPropertyBanner The banner string of the VPN connection. + GetPropertyBanner() (string, error) +} + +func NewVpnConnection(objectPath dbus.ObjectPath) (VpnConnection, error) { + var a vpnConnection + return &a, a.init(NetworkManagerInterface, objectPath) +} + +type vpnConnection struct { + dbusBase +} + +func (a *vpnConnection) GetPath() dbus.ObjectPath { + return a.obj.Path() +} + +func (a *vpnConnection) GetPropertyVpnState() (NmVpnConnectionState, error) { + v, err := a.getUint32Property(VpnConnectionPropertyVpnState) + return NmVpnConnectionState(v), err +} + +func (a *vpnConnection) GetPropertyBanner() (string, error) { + return a.getStringProperty(VpnConnectionPropertyBanner) +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/enums.go b/vendor/github.com/Wifx/gonetworkmanager/v2/enums.go new file mode 100644 index 0000000..ee67e79 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/enums.go @@ -0,0 +1,293 @@ +package gonetworkmanager + +//go:generate stringer -type=NmConnectivity +type NmConnectivity uint32 + +const ( + NmConnectivityUnknown NmConnectivity = 0 // Network connectivity is unknown. This means the connectivity checks are disabled (e.g. on server installations) or has not run yet. The graphical shell should assume the Internet connection might be available and not present a captive portal window. + NmConnectivityNone NmConnectivity = 1 // The host is not connected to any network. There's no active connection that contains a default route to the internet and thus it makes no sense to even attempt a connectivity check. The graphical shell should use this state to indicate the network connection is unavailable. + NmConnectivityPortal NmConnectivity = 2 // The Internet connection is hijacked by a captive portal gateway. The graphical shell may open a sandboxed web browser window (because the captive portals typically attempt a man-in-the-middle attacks against the https connections) for the purpose of authenticating to a gateway and retrigger the connectivity check with CheckConnectivity() when the browser window is dismissed. + NmConnectivityLimited NmConnectivity = 3 // The host is connected to a network, does not appear to be able to reach the full Internet, but a captive portal has not been detected. + NmConnectivityFull NmConnectivity = 4 // The host is connected to a network, and appears to be able to reach the full Internet. +) + +//go:generate stringer -type=NmState +type NmState uint32 + +const ( + NmStateUnknown NmState = 0 // Networking state is unknown. This indicates a daemon error that makes it unable to reasonably assess the state. In such event the applications are expected to assume Internet connectivity might be present and not disable controls that require network access. The graphical shells may hide the network accessibility indicator altogether since no meaningful status indication can be provided. + NmStateAsleep NmState = 10 // Networking is not enabled, the system is being suspended or resumed from suspend. + NmStateDisconnected NmState = 20 // There is no active network connection. The graphical shell should indicate no network connectivity and the applications should not attempt to access the network. + NmStateDisconnecting NmState = 30 // Network connections are being cleaned up. The applications should tear down their network sessions. + NmStateConnecting NmState = 40 // A network connection is being started The graphical shell should indicate the network is being connected while the applications should still make no attempts to connect the network. + NmStateConnectedLocal NmState = 50 // There is only local IPv4 and/or IPv6 connectivity, but no default route to access the Internet. The graphical shell should indicate no network connectivity. + NmStateConnectedSite NmState = 60 // There is only site-wide IPv4 and/or IPv6 connectivity. This means a default route is available, but the Internet connectivity check (see "Connectivity" property) did not succeed. The graphical shell should indicate limited network connectivity. + NmStateConnectedGlobal NmState = 70 // There is global IPv4 and/or IPv6 Internet connectivity This means the Internet connectivity check succeeded, the graphical shell should indicate full network connectivity. +) + +//go:generate stringer -type=NmCheckpointCreateFlags +type NmCheckpointCreateFlags uint32 + +const ( + NmCheckpointCreateFlagsNone NmCheckpointCreateFlags = 0 // no flags + NmCheckpointCreateFlagsDestroyAll NmCheckpointCreateFlags = 0x01 // when creating a new checkpoint, destroy all existing ones. + NmCheckpointCreateFlagsDeleteNewConnections NmCheckpointCreateFlags = 0x02 // upon rollback, delete any new connection added after the checkpoint (Since: 1.6) + NmCheckpointCreateFlagsDisconnectNewDevices NmCheckpointCreateFlags = 0x04 // upon rollback, disconnect any new device appeared after the checkpoint (Since: 1.6) + NmCheckpointCreateFlagsAllowOverlapping NmCheckpointCreateFlags = 0x08 // by default, creating a checkpoint fails if there are already existing checkoints that reference the same devices. With this flag, creation of such checkpoints is allowed, however, if an older checkpoint that references overlapping devices gets rolled back, it will automatically destroy this checkpoint during rollback. This allows to create several overlapping checkpoints in parallel, and rollback to them at will. With the special case that rolling back to an older checkpoint will invalidate all overlapping younger checkpoints. This opts-in that the checkpoint can be automatically destroyed by the rollback of an older checkpoint. (Since: 1.12) +) + +//go:generate stringer -type=NmCapability +type NmCapability uint32 + +const ( + NmCapabilityTeam NmCapability = 1 // Teams can be managed +) + +//go:generate stringer -type=NmMetered +type NmMetered uint32 + +const ( + NmMeteredUnknown NmMetered = 0 // The metered status is unknown + NmMeteredYes NmMetered = 1 // Metered, the value was statically set + NmMeteredNo NmMetered = 2 // Not metered, the value was statically set + NmMeteredGuessYes NmMetered = 3 // Metered, the value was guessed + NmMeteredGuessNo NmMetered = 4 // Not metered, the value was guessed +) + +//go:generate stringer -type=NmDeviceState +type NmDeviceState uint32 + +const ( + NmDeviceStateUnknown NmDeviceState = 0 // the device's state is unknown + NmDeviceStateUnmanaged NmDeviceState = 10 // the device is recognized, but not managed by NetworkManager + NmDeviceStateUnavailable NmDeviceState = 20 // the device is managed by NetworkManager, but is not available for use. Reasons may include the wireless switched off, missing firmware, no ethernet carrier, missing supplicant or modem manager, etc. + NmDeviceStateDisconnected NmDeviceState = 30 // the device can be activated, but is currently idle and not connected to a network. + NmDeviceStatePrepare NmDeviceState = 40 // the device is preparing the connection to the network. This may include operations like changing the MAC address, setting physical link properties, and anything else required to connect to the requested network. + NmDeviceStateConfig NmDeviceState = 50 // the device is connecting to the requested network. This may include operations like associating with the Wi-Fi AP, dialing the modem, connecting to the remote Bluetooth device, etc. + NmDeviceStateNeedAuth NmDeviceState = 60 // the device requires more information to continue connecting to the requested network. This includes secrets like WiFi passphrases, login passwords, PIN codes, etc. + NmDeviceStateIpConfig NmDeviceState = 70 // the device is requesting IPv4 and/or IPv6 addresses and routing information from the network. + NmDeviceStateIpCheck NmDeviceState = 80 // the device is checking whether further action is required for the requested network connection. This may include checking whether only local network access is available, whether a captive portal is blocking access to the Internet, etc. + NmDeviceStateSecondaries NmDeviceState = 90 // the device is waiting for a secondary connection (like a VPN) which must activated before the device can be activated + NmDeviceStateActivated NmDeviceState = 100 // the device has a network connection, either local or global. + NmDeviceStateDeactivating NmDeviceState = 110 // a disconnection from the current network connection was requested, and the device is cleaning up resources used for that connection. The network connection may still be valid. + NmDeviceStateFailed NmDeviceState = 120 // the device failed to connect to the requested network and is cleaning up the connection request +) + +//go:generate stringer -type=NmActiveConnectionState +type NmActiveConnectionState uint32 + +const ( + NmActiveConnectionStateUnknown NmActiveConnectionState = 0 // The state of the connection is unknown + NmActiveConnectionStateActivating NmActiveConnectionState = 1 // A network connection is being prepared + NmActiveConnectionStateActivated NmActiveConnectionState = 2 // There is a connection to the network + NmActiveConnectionStateDeactivating NmActiveConnectionState = 3 // The network connection is being torn down and cleaned up + NmActiveConnectionStateDeactivated NmActiveConnectionState = 4 // The network connection is disconnected and will be removed +) + +//go:generate stringer -type=NmActivationStateFlag +type NmActivationStateFlag uint32 + +const ( + NmActivationStateFlagNone NmActivationStateFlag = 0x00 // an alias for numeric zero, no flags set. + NmActivationStateFlagIsMaster NmActivationStateFlag = 0x01 // the device is a master. + NmActivationStateFlagIsSlave NmActivationStateFlag = 0x02 // the device is a slave. + NmActivationStateFlagLayer2Ready NmActivationStateFlag = 0x04 // layer2 is activated and ready. + NmActivationStateFlagIp4Ready NmActivationStateFlag = 0x08 // IPv4 setting is completed. + NmActivationStateFlagIp6Ready NmActivationStateFlag = 0x10 // IPv6 setting is completed. + NmActivationStateFlagMasterHasSlaves NmActivationStateFlag = 0x20 // The master has any slave devices attached. This only makes sense if the device is a master. + NmActivationStateFlagLifetimeBoundToProfileVisibility NmActivationStateFlag = 0x40 // the lifetime of the activation is bound to the visilibity of the connection profile, which in turn depends on "connection.permissions" and whether a session for the user exists. Since: 1.16 +) + +//go:generate stringer -type=NmDeviceType +type NmDeviceType uint32 + +const ( + NmDeviceTypeUnknown NmDeviceType = 0 // unknown device + NmDeviceTypeGeneric NmDeviceType = 14 // generic support for unrecognized device types + NmDeviceTypeEthernet NmDeviceType = 1 // a wired ethernet device + NmDeviceTypeWifi NmDeviceType = 2 // an 802.11 Wi-Fi device + NmDeviceTypeUnused1 NmDeviceType = 3 // not used + NmDeviceTypeUnused2 NmDeviceType = 4 // not used + NmDeviceTypeBt NmDeviceType = 5 // a Bluetooth device supporting PAN or DUN access protocols + NmDeviceTypeOlpcMesh NmDeviceType = 6 // an OLPC XO mesh networking device + NmDeviceTypeWimax NmDeviceType = 7 // an 802.16e Mobile WiMAX broadband device + NmDeviceTypeModem NmDeviceType = 8 // a modem supporting analog telephone, CDMA/EVDO, GSM/UMTS, or LTE network access protocols + NmDeviceTypeInfiniband NmDeviceType = 9 // an IP-over-InfiniBand device + NmDeviceTypeBond NmDeviceType = 10 // a bond master interface + NmDeviceTypeVlan NmDeviceType = 11 // an 802.1Q VLAN interface + NmDeviceTypeAdsl NmDeviceType = 12 // ADSL modem + NmDeviceTypeBridge NmDeviceType = 13 // a bridge master interface + NmDeviceTypeTeam NmDeviceType = 15 // a team master interface + NmDeviceTypeTun NmDeviceType = 16 // a TUN or TAP interface + NmDeviceTypeIpTunnel NmDeviceType = 17 // a IP tunnel interface + NmDeviceTypeMacvlan NmDeviceType = 18 // a MACVLAN interface + NmDeviceTypeVxlan NmDeviceType = 19 // a VXLAN interface + NmDeviceTypeVeth NmDeviceType = 20 // a VETH interface + NmDeviceTypeMacsec NmDeviceType = 21 // a MACsec interface + NmDeviceTypeDummy NmDeviceType = 22 // a dummy interface + NmDeviceTypePpp NmDeviceType = 23 // a PPP interface + NmDeviceTypeOvsInterface NmDeviceType = 24 // a Open vSwitch interface + NmDeviceTypeOvsPort NmDeviceType = 25 // a Open vSwitch port + NmDeviceTypeOvsBridge NmDeviceType = 26 // a Open vSwitch bridge + NmDeviceTypeWpan NmDeviceType = 27 // a IEEE 802.15.4 (WPAN) MAC Layer Device + NmDeviceType6lowpan NmDeviceType = 28 // 6LoWPAN interface + NmDeviceTypeWireguard NmDeviceType = 29 // a WireGuard interface + NmDeviceTypeWifiP2p NmDeviceType = 30 // an 802.11 Wi-Fi P2P device (Since: 1.16) +) + +//go:generate stringer -type=Nm80211APFlags +type Nm80211APFlags uint32 + +const ( + Nm80211APFlagsNone Nm80211APFlags = 0x0 + Nm80211APFlagsPrivacy Nm80211APFlags = 0x1 +) + +//go:generate stringer -type=Nm80211APSec +type Nm80211APSec uint32 + +const ( + Nm80211APSecNone Nm80211APSec = 0x0 + Nm80211APSecPairWEP40 Nm80211APSec = 0x1 + Nm80211APSecPairWEP104 Nm80211APSec = 0x2 + Nm80211APSecPairTKIP Nm80211APSec = 0x4 + Nm80211APSecPairCCMP Nm80211APSec = 0x8 + Nm80211APSecGroupWEP40 Nm80211APSec = 0x10 + Nm80211APSecGroupWEP104 Nm80211APSec = 0x20 + Nm80211APSecGroupTKIP Nm80211APSec = 0x40 + Nm80211APSecGroupCCMP Nm80211APSec = 0x80 + Nm80211APSecKeyMgmtPSK Nm80211APSec = 0x100 + Nm80211APSecKeyMgmt8021X Nm80211APSec = 0x200 + Nm80211APSecKeyMgmtSAE Nm80211APSec = 0x400 + Nm80211APSecKeyMgmtOWE Nm80211APSec = 0x800 + Nm80211APSecKeyMgmtOWETM Nm80211APSec = 0x1000 +) + +//go:generate stringer -type=Nm80211Mode +type Nm80211Mode uint32 + +const ( + Nm80211ModeUnknown Nm80211Mode = 0 + Nm80211ModeAdhoc Nm80211Mode = 1 + Nm80211ModeInfra Nm80211Mode = 2 + Nm80211ModeAp Nm80211Mode = 3 +) + +//go:generate stringer -type=NmActiveConnectionState +type NmVpnConnectionState uint32 + +const ( + NmVpnConnectionUnknown = 0 //The state of the VPN connection is unknown. + NmVpnConnectionPrepare = 1 //The VPN connection is preparing to connect. + NmVpnConnectionNeedAuth = 2 //The VPN connection needs authorization credentials. + NmVpnConnectionConnect = 3 //The VPN connection is being established. + NmVpnConnectionIpConfigGet = 4 //The VPN connection is getting an IP address. + NmVpnConnectionActivated = 5 //The VPN connection is active. + NmVpnConnectionFailed = 6 //The VPN connection failed. + NmVpnConnectionDisconnected = 7 //The VPN connection is disconnected. +) + +//go:generate stringer -type=NmDeviceStateReason +type NmDeviceStateReason uint32 + +const ( + NmDeviceStateReasonNone = 0 // No reason given + NmDeviceStateReasonUnknown = 1 // Unknown error + NmDeviceStateReasonNowManaged = 2 // Device is now managed + NmDeviceStateReasonNowUnmanaged = 3 // Device is now unmanaged + NmDeviceStateReasonConfigFailed = 4 // The device could not be readied for configuration + NmDeviceStateReasonIpConfigUnavailable = 5 // IP configuration could not be reserved (no available address, timeout, etc) + NmDeviceStateReasonIpConfigExpired = 6 // The IP config is no longer valid + NmDeviceStateReasonNoSecrets = 7 // Secrets were required, but not provided + NmDeviceStateReasonSupplicantDisconnect = 8 // 802.1x supplicant disconnected + NmDeviceStateReasonSupplicantConfigFailed = 9 // 802.1x supplicant configuration failed + NmDeviceStateReasonSupplicantFailed = 10 // 802.1x supplicant failed + NmDeviceStateReasonSupplicantTimeout = 11 // 802.1x supplicant took too long to authenticate + NmDeviceStateReasonPppStartFailed = 12 // PPP service failed to start + NmDeviceStateReasonPppDisconnect = 13 // PPP service disconnected + NmDeviceStateReasonPppFailed = 14 // PPP failed + NmDeviceStateReasonDhcpStartFailed = 15 // DHCP client failed to start + NmDeviceStateReasonDhcpError = 16 // DHCP client error + NmDeviceStateReasonDhcpFailed = 17 // DHCP client failed + NmDeviceStateReasonSharedStartFailed = 18 // Shared connection service failed to start + NmDeviceStateReasonSharedFailed = 19 // Shared connection service failed + NmDeviceStateReasonAutoipStartFailed = 20 // AutoIP service failed to start + NmDeviceStateReasonAutoipError = 21 // AutoIP service error + NmDeviceStateReasonAutoipFailed = 22 // AutoIP service failed + NmDeviceStateReasonModemBusy = 23 // The line is busy + NmDeviceStateReasonModemNoDialTone = 24 // No dial tone + NmDeviceStateReasonModemNoCarrier = 25 // No carrier could be established + NmDeviceStateReasonModemDialTimeout = 26 // The dialing request timed out + NmDeviceStateReasonModemDialFailed = 27 // The dialing attempt failed + NmDeviceStateReasonModemInitFailed = 28 // Modem initialization failed + NmDeviceStateReasonGsmApnFailed = 29 // Failed to select the specified APN + NmDeviceStateReasonGsmRegistrationNotSearching = 30 // Not searching for networks + NmDeviceStateReasonGsmRegistrationDenied = 31 // Network registration denied + NmDeviceStateReasonGsmRegistrationTimeout = 32 // Network registration timed out + NmDeviceStateReasonGsmRegistrationFailed = 33 // Failed to register with the requested network + NmDeviceStateReasonGsmPinCheckFailed = 34 // PIN check failed + NmDeviceStateReasonFirmwareMissing = 35 // Necessary firmware for the device may be missing + NmDeviceStateReasonRemoved = 36 // The device was removed + NmDeviceStateReasonSleeping = 37 // NetworkManager went to sleep + NmDeviceStateReasonConnectionRemoved = 38 // The device's active connection disappeared + NmDeviceStateReasonUserRequested = 39 // Device disconnected by user or client + NmDeviceStateReasonCarrier = 40 // Carrier/link changed + NmDeviceStateReasonConnectionAssumed = 41 // The device's existing connection was assumed + NmDeviceStateReasonSupplicantAvailable = 42 // The supplicant is now available + NmDeviceStateReasonModemNotFound = 43 // The modem could not be found + NmDeviceStateReasonBtFailed = 44 // The Bluetooth connection failed or timed out + NmDeviceStateReasonGsmSimNotInserted = 45 // GSM Modem's SIM Card not inserted + NmDeviceStateReasonGsmSimPinRequired = 46 // GSM Modem's SIM Pin required + NmDeviceStateReasonGsmSimPukRequired = 47 // GSM Modem's SIM Puk required + NmDeviceStateReasonGsmSimWrong = 48 // GSM Modem's SIM wrong + NmDeviceStateReasonInfinibandMode = 49 // InfiniBand device does not support connected mode + NmDeviceStateReasonDependencyFailed = 50 // A dependency of the connection failed + NmDeviceStateReasonBr2684Failed = 51 // Problem with the RFC 2684 Ethernet over ADSL bridge + NmDeviceStateReasonModemManagerUnavailable = 52 // ModemManager not running + NmDeviceStateReasonSsidNotFound = 53 // The Wi-Fi network could not be found + NmDeviceStateReasonSecondaryConnectionFailed = 54 // A secondary connection of the base connection failed + NmDeviceStateReasonDcbFcoeFailed = 55 // DCB or FCoE setup failed + NmDeviceStateReasonTeamdControlFailed = 56 // teamd control failed + NmDeviceStateReasonModemFailed = 57 // Modem failed or no longer available + NmDeviceStateReasonModemAvailable = 58 // Modem now ready and available + NmDeviceStateReasonSimPinIncorrect = 59 // SIM PIN was incorrect + NmDeviceStateReasonNewActivation = 60 // New connection activation was enqueued + NmDeviceStateReasonParentChanged = 61 // the device's parent changed + NmDeviceStateReasonParentManagedChanged = 62 // the device parent's management changed + NmDeviceStateReasonOvsdbFailed = 63 // problem communicating with Open vSwitch database + NmDeviceStateReasonIpAddressDuplicate = 64 // a duplicate IP address was detected + NmDeviceStateReasonIpMethodUnsupported = 65 // The selected IP method is not supported + NmDeviceStateReasonSriovConfigurationFailed = 66 // configuration of SR-IOV parameters failed + NmDeviceStateReasonPeerNotFound = 67 // The Wi-Fi P2P peer could not be found +) + +//go:generate stringer -type=NmActiveConnectionStateReason +type NmActiveConnectionStateReason uint32 + +const ( + NmActiveConnectionStateReasonUnknown = 0 // The reason for the active connection state change is unknown. + NmActiveConnectionStateReasonNone = 1 // No reason was given for the active connection state change. + NmActiveConnectionStateReasonUserDisconnected = 2 // The active connection changed state because the user disconnected it. + NmActiveConnectionStateReasonDeviceDisconnected = 3 // The active connection changed state because the device it was using was disconnected. + NmActiveConnectionStateReasonServiceStopped = 4 // The service providing the VPN connection was stopped. + NmActiveConnectionStateReasonIpConfigInvalid = 5 // The IP config of the active connection was invalid. + NmActiveConnectionStateReasonConnectTimeout = 6 // The connection attempt to the VPN service timed out. + NmActiveConnectionStateReasonServiceStartTimeout = 7 // A timeout occurred while starting the service providing the VPN connection. + NmActiveConnectionStateReasonServiceStartFailed = 8 // Starting the service providing the VPN connection failed. + NmActiveConnectionStateReasonNoSecrets = 9 // Necessary secrets for the connection were not provided. + NmActiveConnectionStateReasonLoginFailed = 10 // Authentication to the server failed. + NmActiveConnectionStateReasonConnectionRemoved = 11 // The connection was deleted from settings. + NmActiveConnectionStateReasonDependencyFailed = 12 // Master connection of this connection failed to activate. + NmActiveConnectionStateReasonDeviceRealizeFailed = 13 // Could not create the software device link. + NmActiveConnectionStateReasonDeviceRemoved = 14 // The device this connection depended on disappeared. +) + +//go:generate stringer -type=NmRollbackResult +type NmRollbackResult uint32 + +const ( + NmRollbackResultOk = 0 // the rollback succeeded. + NmRollbackResultErrNoDevice = 1 // the device no longer exists. + NmRollbackResultErrDeviceUnmanaged = 2 // the device is now unmanaged. + NmRollbackResultErrFailed = 3 // other errors during rollback. +) diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apflags_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apflags_string.go new file mode 100644 index 0000000..8213550 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apflags_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=Nm80211APFlags"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Nm80211APFlagsNone-0] + _ = x[Nm80211APFlagsPrivacy-1] +} + +const _Nm80211APFlags_name = "Nm80211APFlagsNoneNm80211APFlagsPrivacy" + +var _Nm80211APFlags_index = [...]uint8{0, 18, 39} + +func (i Nm80211APFlags) String() string { + if i >= Nm80211APFlags(len(_Nm80211APFlags_index)-1) { + return "Nm80211APFlags(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Nm80211APFlags_name[_Nm80211APFlags_index[i]:_Nm80211APFlags_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apsec_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apsec_string.go new file mode 100644 index 0000000..030ddf3 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211apsec_string.go @@ -0,0 +1,51 @@ +// Code generated by "stringer -type=Nm80211APSec"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Nm80211APSecNone-0] + _ = x[Nm80211APSecPairWEP40-1] + _ = x[Nm80211APSecPairWEP104-2] + _ = x[Nm80211APSecPairTKIP-4] + _ = x[Nm80211APSecPairCCMP-8] + _ = x[Nm80211APSecGroupWEP40-16] + _ = x[Nm80211APSecGroupWEP104-32] + _ = x[Nm80211APSecGroupTKIP-64] + _ = x[Nm80211APSecGroupCCMP-128] + _ = x[Nm80211APSecKeyMgmtPSK-256] + _ = x[Nm80211APSecKeyMgmt8021X-512] + _ = x[Nm80211APSecKeyMgmtSAE-1024] + _ = x[Nm80211APSecKeyMgmtOWE-2048] + _ = x[Nm80211APSecKeyMgmtOWETM-4096] +} + +const _Nm80211APSec_name = "Nm80211APSecNoneNm80211APSecPairWEP40Nm80211APSecPairWEP104Nm80211APSecPairTKIPNm80211APSecPairCCMPNm80211APSecGroupWEP40Nm80211APSecGroupWEP104Nm80211APSecGroupTKIPNm80211APSecGroupCCMPNm80211APSecKeyMgmtPSKNm80211APSecKeyMgmt8021XNm80211APSecKeyMgmtSAENm80211APSecKeyMgmtOWENm80211APSecKeyMgmtOWETM" + +var _Nm80211APSec_map = map[Nm80211APSec]string{ + 0: _Nm80211APSec_name[0:16], + 1: _Nm80211APSec_name[16:37], + 2: _Nm80211APSec_name[37:59], + 4: _Nm80211APSec_name[59:79], + 8: _Nm80211APSec_name[79:99], + 16: _Nm80211APSec_name[99:121], + 32: _Nm80211APSec_name[121:144], + 64: _Nm80211APSec_name[144:165], + 128: _Nm80211APSec_name[165:186], + 256: _Nm80211APSec_name[186:208], + 512: _Nm80211APSec_name[208:232], + 1024: _Nm80211APSec_name[232:254], + 2048: _Nm80211APSec_name[254:276], + 4096: _Nm80211APSec_name[276:300], +} + +func (i Nm80211APSec) String() string { + if str, ok := _Nm80211APSec_map[i]; ok { + return str + } + return "Nm80211APSec(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211mode_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211mode_string.go new file mode 100644 index 0000000..477062f --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nm80211mode_string.go @@ -0,0 +1,26 @@ +// Code generated by "stringer -type=Nm80211Mode"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Nm80211ModeUnknown-0] + _ = x[Nm80211ModeAdhoc-1] + _ = x[Nm80211ModeInfra-2] + _ = x[Nm80211ModeAp-3] +} + +const _Nm80211Mode_name = "Nm80211ModeUnknownNm80211ModeAdhocNm80211ModeInfraNm80211ModeAp" + +var _Nm80211Mode_index = [...]uint8{0, 18, 34, 50, 63} + +func (i Nm80211Mode) String() string { + if i >= Nm80211Mode(len(_Nm80211Mode_index)-1) { + return "Nm80211Mode(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Nm80211Mode_name[_Nm80211Mode_index[i]:_Nm80211Mode_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmactivationstateflag_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmactivationstateflag_string.go new file mode 100644 index 0000000..6444a2c --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmactivationstateflag_string.go @@ -0,0 +1,51 @@ +// Code generated by "stringer -type=NmActivationStateFlag"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmActivationStateFlagNone-0] + _ = x[NmActivationStateFlagIsMaster-1] + _ = x[NmActivationStateFlagIsSlave-2] + _ = x[NmActivationStateFlagLayer2Ready-4] + _ = x[NmActivationStateFlagIp4Ready-8] + _ = x[NmActivationStateFlagIp6Ready-16] + _ = x[NmActivationStateFlagMasterHasSlaves-32] + _ = x[NmActivationStateFlagLifetimeBoundToProfileVisibility-64] +} + +const ( + _NmActivationStateFlag_name_0 = "NmActivationStateFlagNoneNmActivationStateFlagIsMasterNmActivationStateFlagIsSlave" + _NmActivationStateFlag_name_1 = "NmActivationStateFlagLayer2Ready" + _NmActivationStateFlag_name_2 = "NmActivationStateFlagIp4Ready" + _NmActivationStateFlag_name_3 = "NmActivationStateFlagIp6Ready" + _NmActivationStateFlag_name_4 = "NmActivationStateFlagMasterHasSlaves" + _NmActivationStateFlag_name_5 = "NmActivationStateFlagLifetimeBoundToProfileVisibility" +) + +var ( + _NmActivationStateFlag_index_0 = [...]uint8{0, 25, 54, 82} +) + +func (i NmActivationStateFlag) String() string { + switch { + case 0 <= i && i <= 2: + return _NmActivationStateFlag_name_0[_NmActivationStateFlag_index_0[i]:_NmActivationStateFlag_index_0[i+1]] + case i == 4: + return _NmActivationStateFlag_name_1 + case i == 8: + return _NmActivationStateFlag_name_2 + case i == 16: + return _NmActivationStateFlag_name_3 + case i == 32: + return _NmActivationStateFlag_name_4 + case i == 64: + return _NmActivationStateFlag_name_5 + default: + return "NmActivationStateFlag(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmactiveconnectionstate_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmactiveconnectionstate_string.go new file mode 100644 index 0000000..ad2e4ce --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmactiveconnectionstate_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type=NmActiveConnectionState"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmActiveConnectionStateUnknown-0] + _ = x[NmActiveConnectionStateActivating-1] + _ = x[NmActiveConnectionStateActivated-2] + _ = x[NmActiveConnectionStateDeactivating-3] + _ = x[NmActiveConnectionStateDeactivated-4] +} + +const _NmActiveConnectionState_name = "NmActiveConnectionStateUnknownNmActiveConnectionStateActivatingNmActiveConnectionStateActivatedNmActiveConnectionStateDeactivatingNmActiveConnectionStateDeactivated" + +var _NmActiveConnectionState_index = [...]uint8{0, 30, 63, 95, 130, 164} + +func (i NmActiveConnectionState) String() string { + if i >= NmActiveConnectionState(len(_NmActiveConnectionState_index)-1) { + return "NmActiveConnectionState(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _NmActiveConnectionState_name[_NmActiveConnectionState_index[i]:_NmActiveConnectionState_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmcapability_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmcapability_string.go new file mode 100644 index 0000000..2fcbf34 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmcapability_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type=NmCapability"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmCapabilityTeam-1] +} + +const _NmCapability_name = "NmCapabilityTeam" + +var _NmCapability_index = [...]uint8{0, 16} + +func (i NmCapability) String() string { + i -= 1 + if i >= NmCapability(len(_NmCapability_index)-1) { + return "NmCapability(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _NmCapability_name[_NmCapability_index[i]:_NmCapability_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmcheckpointcreateflags_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmcheckpointcreateflags_string.go new file mode 100644 index 0000000..8e7cc99 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmcheckpointcreateflags_string.go @@ -0,0 +1,39 @@ +// Code generated by "stringer -type=NmCheckpointCreateFlags"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmCheckpointCreateFlagsNone-0] + _ = x[NmCheckpointCreateFlagsDestroyAll-1] + _ = x[NmCheckpointCreateFlagsDeleteNewConnections-2] + _ = x[NmCheckpointCreateFlagsDisconnectNewDevices-4] + _ = x[NmCheckpointCreateFlagsAllowOverlapping-8] +} + +const ( + _NmCheckpointCreateFlags_name_0 = "NmCheckpointCreateFlagsNoneNmCheckpointCreateFlagsDestroyAllNmCheckpointCreateFlagsDeleteNewConnections" + _NmCheckpointCreateFlags_name_1 = "NmCheckpointCreateFlagsDisconnectNewDevices" + _NmCheckpointCreateFlags_name_2 = "NmCheckpointCreateFlagsAllowOverlapping" +) + +var ( + _NmCheckpointCreateFlags_index_0 = [...]uint8{0, 27, 60, 103} +) + +func (i NmCheckpointCreateFlags) String() string { + switch { + case 0 <= i && i <= 2: + return _NmCheckpointCreateFlags_name_0[_NmCheckpointCreateFlags_index_0[i]:_NmCheckpointCreateFlags_index_0[i+1]] + case i == 4: + return _NmCheckpointCreateFlags_name_1 + case i == 8: + return _NmCheckpointCreateFlags_name_2 + default: + return "NmCheckpointCreateFlags(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmconnectivity_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmconnectivity_string.go new file mode 100644 index 0000000..cb8605b --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmconnectivity_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type=NmConnectivity"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmConnectivityUnknown-0] + _ = x[NmConnectivityNone-1] + _ = x[NmConnectivityPortal-2] + _ = x[NmConnectivityLimited-3] + _ = x[NmConnectivityFull-4] +} + +const _NmConnectivity_name = "NmConnectivityUnknownNmConnectivityNoneNmConnectivityPortalNmConnectivityLimitedNmConnectivityFull" + +var _NmConnectivity_index = [...]uint8{0, 21, 39, 59, 80, 98} + +func (i NmConnectivity) String() string { + if i >= NmConnectivity(len(_NmConnectivity_index)-1) { + return "NmConnectivity(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _NmConnectivity_name[_NmConnectivity_index[i]:_NmConnectivity_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicestate_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicestate_string.go new file mode 100644 index 0000000..1243ea7 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicestate_string.go @@ -0,0 +1,49 @@ +// Code generated by "stringer -type=NmDeviceState"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmDeviceStateUnknown-0] + _ = x[NmDeviceStateUnmanaged-10] + _ = x[NmDeviceStateUnavailable-20] + _ = x[NmDeviceStateDisconnected-30] + _ = x[NmDeviceStatePrepare-40] + _ = x[NmDeviceStateConfig-50] + _ = x[NmDeviceStateNeedAuth-60] + _ = x[NmDeviceStateIpConfig-70] + _ = x[NmDeviceStateIpCheck-80] + _ = x[NmDeviceStateSecondaries-90] + _ = x[NmDeviceStateActivated-100] + _ = x[NmDeviceStateDeactivating-110] + _ = x[NmDeviceStateFailed-120] +} + +const _NmDeviceState_name = "NmDeviceStateUnknownNmDeviceStateUnmanagedNmDeviceStateUnavailableNmDeviceStateDisconnectedNmDeviceStatePrepareNmDeviceStateConfigNmDeviceStateNeedAuthNmDeviceStateIpConfigNmDeviceStateIpCheckNmDeviceStateSecondariesNmDeviceStateActivatedNmDeviceStateDeactivatingNmDeviceStateFailed" + +var _NmDeviceState_map = map[NmDeviceState]string{ + 0: _NmDeviceState_name[0:20], + 10: _NmDeviceState_name[20:42], + 20: _NmDeviceState_name[42:66], + 30: _NmDeviceState_name[66:91], + 40: _NmDeviceState_name[91:111], + 50: _NmDeviceState_name[111:130], + 60: _NmDeviceState_name[130:151], + 70: _NmDeviceState_name[151:172], + 80: _NmDeviceState_name[172:192], + 90: _NmDeviceState_name[192:216], + 100: _NmDeviceState_name[216:238], + 110: _NmDeviceState_name[238:263], + 120: _NmDeviceState_name[263:282], +} + +func (i NmDeviceState) String() string { + if str, ok := _NmDeviceState_map[i]; ok { + return str + } + return "NmDeviceState(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicetype_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicetype_string.go new file mode 100644 index 0000000..d5003b5 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmdevicetype_string.go @@ -0,0 +1,53 @@ +// Code generated by "stringer -type=NmDeviceType"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmDeviceTypeUnknown-0] + _ = x[NmDeviceTypeGeneric-14] + _ = x[NmDeviceTypeEthernet-1] + _ = x[NmDeviceTypeWifi-2] + _ = x[NmDeviceTypeUnused1-3] + _ = x[NmDeviceTypeUnused2-4] + _ = x[NmDeviceTypeBt-5] + _ = x[NmDeviceTypeOlpcMesh-6] + _ = x[NmDeviceTypeWimax-7] + _ = x[NmDeviceTypeModem-8] + _ = x[NmDeviceTypeInfiniband-9] + _ = x[NmDeviceTypeBond-10] + _ = x[NmDeviceTypeVlan-11] + _ = x[NmDeviceTypeAdsl-12] + _ = x[NmDeviceTypeBridge-13] + _ = x[NmDeviceTypeTeam-15] + _ = x[NmDeviceTypeTun-16] + _ = x[NmDeviceTypeIpTunnel-17] + _ = x[NmDeviceTypeMacvlan-18] + _ = x[NmDeviceTypeVxlan-19] + _ = x[NmDeviceTypeVeth-20] + _ = x[NmDeviceTypeMacsec-21] + _ = x[NmDeviceTypeDummy-22] + _ = x[NmDeviceTypePpp-23] + _ = x[NmDeviceTypeOvsInterface-24] + _ = x[NmDeviceTypeOvsPort-25] + _ = x[NmDeviceTypeOvsBridge-26] + _ = x[NmDeviceTypeWpan-27] + _ = x[NmDeviceType6lowpan-28] + _ = x[NmDeviceTypeWireguard-29] + _ = x[NmDeviceTypeWifiP2p-30] +} + +const _NmDeviceType_name = "NmDeviceTypeUnknownNmDeviceTypeEthernetNmDeviceTypeWifiNmDeviceTypeUnused1NmDeviceTypeUnused2NmDeviceTypeBtNmDeviceTypeOlpcMeshNmDeviceTypeWimaxNmDeviceTypeModemNmDeviceTypeInfinibandNmDeviceTypeBondNmDeviceTypeVlanNmDeviceTypeAdslNmDeviceTypeBridgeNmDeviceTypeGenericNmDeviceTypeTeamNmDeviceTypeTunNmDeviceTypeIpTunnelNmDeviceTypeMacvlanNmDeviceTypeVxlanNmDeviceTypeVethNmDeviceTypeMacsecNmDeviceTypeDummyNmDeviceTypePppNmDeviceTypeOvsInterfaceNmDeviceTypeOvsPortNmDeviceTypeOvsBridgeNmDeviceTypeWpanNmDeviceType6lowpanNmDeviceTypeWireguardNmDeviceTypeWifiP2p" + +var _NmDeviceType_index = [...]uint16{0, 19, 39, 55, 74, 93, 107, 127, 144, 161, 183, 199, 215, 231, 249, 268, 284, 299, 319, 338, 355, 371, 389, 406, 421, 445, 464, 485, 501, 520, 541, 560} + +func (i NmDeviceType) String() string { + if i >= NmDeviceType(len(_NmDeviceType_index)-1) { + return "NmDeviceType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _NmDeviceType_name[_NmDeviceType_index[i]:_NmDeviceType_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmmetered_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmmetered_string.go new file mode 100644 index 0000000..0723c13 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmmetered_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type=NmMetered"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmMeteredUnknown-0] + _ = x[NmMeteredYes-1] + _ = x[NmMeteredNo-2] + _ = x[NmMeteredGuessYes-3] + _ = x[NmMeteredGuessNo-4] +} + +const _NmMetered_name = "NmMeteredUnknownNmMeteredYesNmMeteredNoNmMeteredGuessYesNmMeteredGuessNo" + +var _NmMetered_index = [...]uint8{0, 16, 28, 39, 56, 72} + +func (i NmMetered) String() string { + if i >= NmMetered(len(_NmMetered_index)-1) { + return "NmMetered(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _NmMetered_name[_NmMetered_index[i]:_NmMetered_index[i+1]] +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/nmstate_string.go b/vendor/github.com/Wifx/gonetworkmanager/v2/nmstate_string.go new file mode 100644 index 0000000..30dcaf4 --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/nmstate_string.go @@ -0,0 +1,53 @@ +// Code generated by "stringer -type=NmState"; DO NOT EDIT. + +package gonetworkmanager + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[NmStateUnknown-0] + _ = x[NmStateAsleep-10] + _ = x[NmStateDisconnected-20] + _ = x[NmStateDisconnecting-30] + _ = x[NmStateConnecting-40] + _ = x[NmStateConnectedLocal-50] + _ = x[NmStateConnectedSite-60] + _ = x[NmStateConnectedGlobal-70] +} + +const ( + _NmState_name_0 = "NmStateUnknown" + _NmState_name_1 = "NmStateAsleep" + _NmState_name_2 = "NmStateDisconnected" + _NmState_name_3 = "NmStateDisconnecting" + _NmState_name_4 = "NmStateConnecting" + _NmState_name_5 = "NmStateConnectedLocal" + _NmState_name_6 = "NmStateConnectedSite" + _NmState_name_7 = "NmStateConnectedGlobal" +) + +func (i NmState) String() string { + switch { + case i == 0: + return _NmState_name_0 + case i == 10: + return _NmState_name_1 + case i == 20: + return _NmState_name_2 + case i == 30: + return _NmState_name_3 + case i == 40: + return _NmState_name_4 + case i == 50: + return _NmState_name_5 + case i == 60: + return _NmState_name_6 + case i == 70: + return _NmState_name_7 + default: + return "NmState(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/vendor/github.com/Wifx/gonetworkmanager/v2/utils.go b/vendor/github.com/Wifx/gonetworkmanager/v2/utils.go new file mode 100644 index 0000000..4e1f01b --- /dev/null +++ b/vendor/github.com/Wifx/gonetworkmanager/v2/utils.go @@ -0,0 +1,282 @@ +package gonetworkmanager + +import ( + "encoding/binary" + "fmt" + "net" + + "github.com/godbus/dbus/v5" +) + +const ( + dbusMethodAddMatch = "org.freedesktop.DBus.AddMatch" +) + +type dbusBase struct { + conn *dbus.Conn + obj dbus.BusObject +} + +func (d *dbusBase) init(iface string, objectPath dbus.ObjectPath) error { + var err error + + d.conn, err = dbus.SystemBus() + if err != nil { + return err + } + + d.obj = d.conn.Object(iface, objectPath) + + return nil +} + +func (d *dbusBase) call(method string, args ...interface{}) error { + return d.obj.Call(method, 0, args...).Err +} + +func (d *dbusBase) callWithReturn(ret interface{}, method string, args ...interface{}) error { + return d.obj.Call(method, 0, args...).Store(ret) +} + +func (d *dbusBase) callWithReturn2(ret1 interface{}, ret2 interface{}, method string, args ...interface{}) error { + return d.obj.Call(method, 0, args...).Store(ret1, ret2) +} + +func (d *dbusBase) subscribe(iface, member string) { + rule := fmt.Sprintf("type='signal',interface='%s',path='%s',member='%s'", + iface, d.obj.Path(), NetworkManagerInterface) + d.conn.BusObject().Call(dbusMethodAddMatch, 0, rule) +} + +func (d *dbusBase) subscribeNamespace(namespace string) { + rule := fmt.Sprintf("type='signal',path_namespace='%s'", namespace) + d.conn.BusObject().Call(dbusMethodAddMatch, 0, rule) +} + +func (d *dbusBase) getProperty(iface string) (interface{}, error) { + variant, err := d.obj.GetProperty(iface) + return variant.Value(), err +} + +func (d *dbusBase) setProperty(iface string, value interface{}) error { + err := d.obj.SetProperty(iface, dbus.MakeVariant(value)) + return err +} + +func (d *dbusBase) getObjectProperty(iface string) (value dbus.ObjectPath, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(dbus.ObjectPath) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceObjectProperty(iface string) (value []dbus.ObjectPath, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([]dbus.ObjectPath) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getBoolProperty(iface string) (value bool, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(bool) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getStringProperty(iface string) (value string, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(string) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceStringProperty(iface string) (value []string, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([]string) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceSliceByteProperty(iface string) (value [][]byte, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([][]byte) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getMapStringVariantProperty(iface string) (value map[string]dbus.Variant, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(map[string]dbus.Variant) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getUint8Property(iface string) (value uint8, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(uint8) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getUint32Property(iface string) (value uint32, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(uint32) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getInt32Property(iface string) (value int32, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(int32) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getInt64Property(iface string) (value int64, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(int64) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getUint64Property(iface string) (value uint64, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.(uint64) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceUint32Property(iface string) (value []uint32, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([]uint32) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceSliceUint32Property(iface string) (value [][]uint32, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([][]uint32) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceMapStringVariantProperty(iface string) (value []map[string]dbus.Variant, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([]map[string]dbus.Variant) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func (d *dbusBase) getSliceByteProperty(iface string) (value []byte, err error) { + prop, err := d.getProperty(iface) + if err != nil { + return + } + value, ok := prop.([]byte) + if !ok { + err = makeErrVariantType(iface) + return + } + return +} + +func makeErrVariantType(iface string) error { + return fmt.Errorf("unexpected variant type for '%s'", iface) +} + +func ip4ToString(ip uint32) string { + bs := []byte{0, 0, 0, 0} + binary.LittleEndian.PutUint32(bs, ip) + return net.IP(bs).String() +} diff --git a/vendor/github.com/google/uuid/CHANGELOG.md b/vendor/github.com/google/uuid/CHANGELOG.md deleted file mode 100644 index 7ec5ac7..0000000 --- a/vendor/github.com/google/uuid/CHANGELOG.md +++ /dev/null @@ -1,41 +0,0 @@ -# Changelog - -## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16) - - -### Features - -* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3)) - - -### Bug Fixes - -* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06)) -* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6)) - -## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12) - - -### Features - -* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29)) - -## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26) - - -### Features - -* UUIDs slice type with Strings() convenience method ([#133](https://github.com/google/uuid/issues/133)) ([cd5fbbd](https://github.com/google/uuid/commit/cd5fbbdd02f3e3467ac18940e07e062be1f864b4)) - -### Fixes - -* Clarify that Parse's job is to parse but not necessarily validate strings. (Documents current behavior) - -## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18) - - -### Bug Fixes - -* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0)) - -## Changelog diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md deleted file mode 100644 index a502fdc..0000000 --- a/vendor/github.com/google/uuid/CONTRIBUTING.md +++ /dev/null @@ -1,26 +0,0 @@ -# How to contribute - -We definitely welcome patches and contribution to this project! - -### Tips - -Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org). - -Always try to include a test case! If it is not possible or not necessary, -please explain why in the pull request description. - -### Releasing - -Commits that would precipitate a SemVer change, as described in the Conventional -Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action) -to create a release candidate pull request. Once submitted, `release-please` -will create a release. - -For tips on how to work with `release-please`, see its documentation. - -### Legal requirements - -In order to protect both you and ourselves, you will need to sign the -[Contributor License Agreement](https://cla.developers.google.com/clas). - -You may have already signed it for other Google projects. diff --git a/vendor/github.com/google/uuid/CONTRIBUTORS b/vendor/github.com/google/uuid/CONTRIBUTORS deleted file mode 100644 index b4bb97f..0000000 --- a/vendor/github.com/google/uuid/CONTRIBUTORS +++ /dev/null @@ -1,9 +0,0 @@ -Paul Borman -bmatsuo -shawnps -theory -jboverfelt -dsymonds -cd1 -wallclockbuilder -dansouza diff --git a/vendor/github.com/google/uuid/LICENSE b/vendor/github.com/google/uuid/LICENSE deleted file mode 100644 index 5dc6826..0000000 --- a/vendor/github.com/google/uuid/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009,2014 Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md deleted file mode 100644 index 3e9a618..0000000 --- a/vendor/github.com/google/uuid/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# uuid -The uuid package generates and inspects UUIDs based on -[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) -and DCE 1.1: Authentication and Security Services. - -This package is based on the github.com/pborman/uuid package (previously named -code.google.com/p/go-uuid). It differs from these earlier packages in that -a UUID is a 16 byte array rather than a byte slice. One loss due to this -change is the ability to represent an invalid UUID (vs a NIL UUID). - -###### Install -```sh -go get github.com/google/uuid -``` - -###### Documentation -[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid) - -Full `go doc` style documentation for the package can be viewed online without -installing this package by using the GoDoc site here: -http://pkg.go.dev/github.com/google/uuid diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go deleted file mode 100644 index fa820b9..0000000 --- a/vendor/github.com/google/uuid/dce.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "encoding/binary" - "fmt" - "os" -) - -// A Domain represents a Version 2 domain -type Domain byte - -// Domain constants for DCE Security (Version 2) UUIDs. -const ( - Person = Domain(0) - Group = Domain(1) - Org = Domain(2) -) - -// NewDCESecurity returns a DCE Security (Version 2) UUID. -// -// The domain should be one of Person, Group or Org. -// On a POSIX system the id should be the users UID for the Person -// domain and the users GID for the Group. The meaning of id for -// the domain Org or on non-POSIX systems is site defined. -// -// For a given domain/id pair the same token may be returned for up to -// 7 minutes and 10 seconds. -func NewDCESecurity(domain Domain, id uint32) (UUID, error) { - uuid, err := NewUUID() - if err == nil { - uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2 - uuid[9] = byte(domain) - binary.BigEndian.PutUint32(uuid[0:], id) - } - return uuid, err -} - -// NewDCEPerson returns a DCE Security (Version 2) UUID in the person -// domain with the id returned by os.Getuid. -// -// NewDCESecurity(Person, uint32(os.Getuid())) -func NewDCEPerson() (UUID, error) { - return NewDCESecurity(Person, uint32(os.Getuid())) -} - -// NewDCEGroup returns a DCE Security (Version 2) UUID in the group -// domain with the id returned by os.Getgid. -// -// NewDCESecurity(Group, uint32(os.Getgid())) -func NewDCEGroup() (UUID, error) { - return NewDCESecurity(Group, uint32(os.Getgid())) -} - -// Domain returns the domain for a Version 2 UUID. Domains are only defined -// for Version 2 UUIDs. -func (uuid UUID) Domain() Domain { - return Domain(uuid[9]) -} - -// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2 -// UUIDs. -func (uuid UUID) ID() uint32 { - return binary.BigEndian.Uint32(uuid[0:4]) -} - -func (d Domain) String() string { - switch d { - case Person: - return "Person" - case Group: - return "Group" - case Org: - return "Org" - } - return fmt.Sprintf("Domain%d", int(d)) -} diff --git a/vendor/github.com/google/uuid/doc.go b/vendor/github.com/google/uuid/doc.go deleted file mode 100644 index 5b8a4b9..0000000 --- a/vendor/github.com/google/uuid/doc.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package uuid generates and inspects UUIDs. -// -// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security -// Services. -// -// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to -// maps or compared directly. -package uuid diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go deleted file mode 100644 index dc60082..0000000 --- a/vendor/github.com/google/uuid/hash.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "crypto/md5" - "crypto/sha1" - "hash" -) - -// Well known namespace IDs and UUIDs -var ( - NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) - NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) - NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) - NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) - Nil UUID // empty UUID, all zeros - - // The Max UUID is special form of UUID that is specified to have all 128 bits set to 1. - Max = UUID{ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - } -) - -// NewHash returns a new UUID derived from the hash of space concatenated with -// data generated by h. The hash should be at least 16 byte in length. The -// first 16 bytes of the hash are used to form the UUID. The version of the -// UUID will be the lower 4 bits of version. NewHash is used to implement -// NewMD5 and NewSHA1. -func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID { - h.Reset() - h.Write(space[:]) //nolint:errcheck - h.Write(data) //nolint:errcheck - s := h.Sum(nil) - var uuid UUID - copy(uuid[:], s) - uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4) - uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant - return uuid -} - -// NewMD5 returns a new MD5 (Version 3) UUID based on the -// supplied name space and data. It is the same as calling: -// -// NewHash(md5.New(), space, data, 3) -func NewMD5(space UUID, data []byte) UUID { - return NewHash(md5.New(), space, data, 3) -} - -// NewSHA1 returns a new SHA1 (Version 5) UUID based on the -// supplied name space and data. It is the same as calling: -// -// NewHash(sha1.New(), space, data, 5) -func NewSHA1(space UUID, data []byte) UUID { - return NewHash(sha1.New(), space, data, 5) -} diff --git a/vendor/github.com/google/uuid/marshal.go b/vendor/github.com/google/uuid/marshal.go deleted file mode 100644 index 14bd340..0000000 --- a/vendor/github.com/google/uuid/marshal.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "fmt" - -// MarshalText implements encoding.TextMarshaler. -func (uuid UUID) MarshalText() ([]byte, error) { - var js [36]byte - encodeHex(js[:], uuid) - return js[:], nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (uuid *UUID) UnmarshalText(data []byte) error { - id, err := ParseBytes(data) - if err != nil { - return err - } - *uuid = id - return nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (uuid UUID) MarshalBinary() ([]byte, error) { - return uuid[:], nil -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (uuid *UUID) UnmarshalBinary(data []byte) error { - if len(data) != 16 { - return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) - } - copy(uuid[:], data) - return nil -} diff --git a/vendor/github.com/google/uuid/node.go b/vendor/github.com/google/uuid/node.go deleted file mode 100644 index d651a2b..0000000 --- a/vendor/github.com/google/uuid/node.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "sync" -) - -var ( - nodeMu sync.Mutex - ifname string // name of interface being used - nodeID [6]byte // hardware for version 1 UUIDs - zeroID [6]byte // nodeID with only 0's -) - -// NodeInterface returns the name of the interface from which the NodeID was -// derived. The interface "user" is returned if the NodeID was set by -// SetNodeID. -func NodeInterface() string { - defer nodeMu.Unlock() - nodeMu.Lock() - return ifname -} - -// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs. -// If name is "" then the first usable interface found will be used or a random -// Node ID will be generated. If a named interface cannot be found then false -// is returned. -// -// SetNodeInterface never fails when name is "". -func SetNodeInterface(name string) bool { - defer nodeMu.Unlock() - nodeMu.Lock() - return setNodeInterface(name) -} - -func setNodeInterface(name string) bool { - iname, addr := getHardwareInterface(name) // null implementation for js - if iname != "" && addr != nil { - ifname = iname - copy(nodeID[:], addr) - return true - } - - // We found no interfaces with a valid hardware address. If name - // does not specify a specific interface generate a random Node ID - // (section 4.1.6) - if name == "" { - ifname = "random" - randomBits(nodeID[:]) - return true - } - return false -} - -// NodeID returns a slice of a copy of the current Node ID, setting the Node ID -// if not already set. -func NodeID() []byte { - defer nodeMu.Unlock() - nodeMu.Lock() - if nodeID == zeroID { - setNodeInterface("") - } - nid := nodeID - return nid[:] -} - -// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes -// of id are used. If id is less than 6 bytes then false is returned and the -// Node ID is not set. -func SetNodeID(id []byte) bool { - if len(id) < 6 { - return false - } - defer nodeMu.Unlock() - nodeMu.Lock() - copy(nodeID[:], id) - ifname = "user" - return true -} - -// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is -// not valid. The NodeID is only well defined for version 1 and 2 UUIDs. -func (uuid UUID) NodeID() []byte { - var node [6]byte - copy(node[:], uuid[10:]) - return node[:] -} diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go deleted file mode 100644 index b2a0bc8..0000000 --- a/vendor/github.com/google/uuid/node_js.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build js - -package uuid - -// getHardwareInterface returns nil values for the JS version of the code. -// This removes the "net" dependency, because it is not used in the browser. -// Using the "net" library inflates the size of the transpiled JS code by 673k bytes. -func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go deleted file mode 100644 index 0cbbcdd..0000000 --- a/vendor/github.com/google/uuid/node_net.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !js - -package uuid - -import "net" - -var interfaces []net.Interface // cached list of interfaces - -// getHardwareInterface returns the name and hardware address of interface name. -// If name is "" then the name and hardware address of one of the system's -// interfaces is returned. If no interfaces are found (name does not exist or -// there are no interfaces) then "", nil is returned. -// -// Only addresses of at least 6 bytes are returned. -func getHardwareInterface(name string) (string, []byte) { - if interfaces == nil { - var err error - interfaces, err = net.Interfaces() - if err != nil { - return "", nil - } - } - for _, ifs := range interfaces { - if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) { - return ifs.Name, ifs.HardwareAddr - } - } - return "", nil -} diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go deleted file mode 100644 index d7fcbf2..0000000 --- a/vendor/github.com/google/uuid/null.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2021 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "bytes" - "database/sql/driver" - "encoding/json" - "fmt" -) - -var jsonNull = []byte("null") - -// NullUUID represents a UUID that may be null. -// NullUUID implements the SQL driver.Scanner interface so -// it can be used as a scan destination: -// -// var u uuid.NullUUID -// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) -// ... -// if u.Valid { -// // use u.UUID -// } else { -// // NULL value -// } -// -type NullUUID struct { - UUID UUID - Valid bool // Valid is true if UUID is not NULL -} - -// Scan implements the SQL driver.Scanner interface. -func (nu *NullUUID) Scan(value interface{}) error { - if value == nil { - nu.UUID, nu.Valid = Nil, false - return nil - } - - err := nu.UUID.Scan(value) - if err != nil { - nu.Valid = false - return err - } - - nu.Valid = true - return nil -} - -// Value implements the driver Valuer interface. -func (nu NullUUID) Value() (driver.Value, error) { - if !nu.Valid { - return nil, nil - } - // Delegate to UUID Value function - return nu.UUID.Value() -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (nu NullUUID) MarshalBinary() ([]byte, error) { - if nu.Valid { - return nu.UUID[:], nil - } - - return []byte(nil), nil -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (nu *NullUUID) UnmarshalBinary(data []byte) error { - if len(data) != 16 { - return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) - } - copy(nu.UUID[:], data) - nu.Valid = true - return nil -} - -// MarshalText implements encoding.TextMarshaler. -func (nu NullUUID) MarshalText() ([]byte, error) { - if nu.Valid { - return nu.UUID.MarshalText() - } - - return jsonNull, nil -} - -// UnmarshalText implements encoding.TextUnmarshaler. -func (nu *NullUUID) UnmarshalText(data []byte) error { - id, err := ParseBytes(data) - if err != nil { - nu.Valid = false - return err - } - nu.UUID = id - nu.Valid = true - return nil -} - -// MarshalJSON implements json.Marshaler. -func (nu NullUUID) MarshalJSON() ([]byte, error) { - if nu.Valid { - return json.Marshal(nu.UUID) - } - - return jsonNull, nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (nu *NullUUID) UnmarshalJSON(data []byte) error { - if bytes.Equal(data, jsonNull) { - *nu = NullUUID{} - return nil // valid null UUID - } - err := json.Unmarshal(data, &nu.UUID) - nu.Valid = err == nil - return err -} diff --git a/vendor/github.com/google/uuid/sql.go b/vendor/github.com/google/uuid/sql.go deleted file mode 100644 index 2e02ec0..0000000 --- a/vendor/github.com/google/uuid/sql.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "database/sql/driver" - "fmt" -) - -// Scan implements sql.Scanner so UUIDs can be read from databases transparently. -// Currently, database types that map to string and []byte are supported. Please -// consult database-specific driver documentation for matching types. -func (uuid *UUID) Scan(src interface{}) error { - switch src := src.(type) { - case nil: - return nil - - case string: - // if an empty UUID comes from a table, we return a null UUID - if src == "" { - return nil - } - - // see Parse for required string format - u, err := Parse(src) - if err != nil { - return fmt.Errorf("Scan: %v", err) - } - - *uuid = u - - case []byte: - // if an empty UUID comes from a table, we return a null UUID - if len(src) == 0 { - return nil - } - - // assumes a simple slice of bytes if 16 bytes - // otherwise attempts to parse - if len(src) != 16 { - return uuid.Scan(string(src)) - } - copy((*uuid)[:], src) - - default: - return fmt.Errorf("Scan: unable to scan type %T into UUID", src) - } - - return nil -} - -// Value implements sql.Valuer so that UUIDs can be written to databases -// transparently. Currently, UUIDs map to strings. Please consult -// database-specific driver documentation for matching types. -func (uuid UUID) Value() (driver.Value, error) { - return uuid.String(), nil -} diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go deleted file mode 100644 index c351129..0000000 --- a/vendor/github.com/google/uuid/time.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "encoding/binary" - "sync" - "time" -) - -// A Time represents a time as the number of 100's of nanoseconds since 15 Oct -// 1582. -type Time int64 - -const ( - lillian = 2299160 // Julian day of 15 Oct 1582 - unix = 2440587 // Julian day of 1 Jan 1970 - epoch = unix - lillian // Days between epochs - g1582 = epoch * 86400 // seconds between epochs - g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs -) - -var ( - timeMu sync.Mutex - lasttime uint64 // last time we returned - clockSeq uint16 // clock sequence for this run - - timeNow = time.Now // for testing -) - -// UnixTime converts t the number of seconds and nanoseconds using the Unix -// epoch of 1 Jan 1970. -func (t Time) UnixTime() (sec, nsec int64) { - sec = int64(t - g1582ns100) - nsec = (sec % 10000000) * 100 - sec /= 10000000 - return sec, nsec -} - -// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and -// clock sequence as well as adjusting the clock sequence as needed. An error -// is returned if the current time cannot be determined. -func GetTime() (Time, uint16, error) { - defer timeMu.Unlock() - timeMu.Lock() - return getTime() -} - -func getTime() (Time, uint16, error) { - t := timeNow() - - // If we don't have a clock sequence already, set one. - if clockSeq == 0 { - setClockSequence(-1) - } - now := uint64(t.UnixNano()/100) + g1582ns100 - - // If time has gone backwards with this clock sequence then we - // increment the clock sequence - if now <= lasttime { - clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000 - } - lasttime = now - return Time(now), clockSeq, nil -} - -// ClockSequence returns the current clock sequence, generating one if not -// already set. The clock sequence is only used for Version 1 UUIDs. -// -// The uuid package does not use global static storage for the clock sequence or -// the last time a UUID was generated. Unless SetClockSequence is used, a new -// random clock sequence is generated the first time a clock sequence is -// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) -func ClockSequence() int { - defer timeMu.Unlock() - timeMu.Lock() - return clockSequence() -} - -func clockSequence() int { - if clockSeq == 0 { - setClockSequence(-1) - } - return int(clockSeq & 0x3fff) -} - -// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to -// -1 causes a new sequence to be generated. -func SetClockSequence(seq int) { - defer timeMu.Unlock() - timeMu.Lock() - setClockSequence(seq) -} - -func setClockSequence(seq int) { - if seq == -1 { - var b [2]byte - randomBits(b[:]) // clock sequence - seq = int(b[0])<<8 | int(b[1]) - } - oldSeq := clockSeq - clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant - if oldSeq != clockSeq { - lasttime = 0 - } -} - -// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in -// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs. -func (uuid UUID) Time() Time { - var t Time - switch uuid.Version() { - case 6: - time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110 - t = Time(time) - case 7: - time := binary.BigEndian.Uint64(uuid[:8]) - t = Time((time>>16)*10000 + g1582ns100) - default: // forward compatible - time := int64(binary.BigEndian.Uint32(uuid[0:4])) - time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 - time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 - t = Time(time) - } - return t -} - -// ClockSequence returns the clock sequence encoded in uuid. -// The clock sequence is only well defined for version 1 and 2 UUIDs. -func (uuid UUID) ClockSequence() int { - return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff -} diff --git a/vendor/github.com/google/uuid/util.go b/vendor/github.com/google/uuid/util.go deleted file mode 100644 index 5ea6c73..0000000 --- a/vendor/github.com/google/uuid/util.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "io" -) - -// randomBits completely fills slice b with random data. -func randomBits(b []byte) { - if _, err := io.ReadFull(rander, b); err != nil { - panic(err.Error()) // rand should never fail - } -} - -// xvalues returns the value of a byte as a hexadecimal digit or 255. -var xvalues = [256]byte{ - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, -} - -// xtob converts hex characters x1 and x2 into a byte. -func xtob(x1, x2 byte) (byte, bool) { - b1 := xvalues[x1] - b2 := xvalues[x2] - return (b1 << 4) | b2, b1 != 255 && b2 != 255 -} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go deleted file mode 100644 index 5232b48..0000000 --- a/vendor/github.com/google/uuid/uuid.go +++ /dev/null @@ -1,365 +0,0 @@ -// Copyright 2018 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "bytes" - "crypto/rand" - "encoding/hex" - "errors" - "fmt" - "io" - "strings" - "sync" -) - -// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC -// 4122. -type UUID [16]byte - -// A Version represents a UUID's version. -type Version byte - -// A Variant represents a UUID's variant. -type Variant byte - -// Constants returned by Variant. -const ( - Invalid = Variant(iota) // Invalid UUID - RFC4122 // The variant specified in RFC4122 - Reserved // Reserved, NCS backward compatibility. - Microsoft // Reserved, Microsoft Corporation backward compatibility. - Future // Reserved for future definition. -) - -const randPoolSize = 16 * 16 - -var ( - rander = rand.Reader // random function - poolEnabled = false - poolMu sync.Mutex - poolPos = randPoolSize // protected with poolMu - pool [randPoolSize]byte // protected with poolMu -) - -type invalidLengthError struct{ len int } - -func (err invalidLengthError) Error() string { - return fmt.Sprintf("invalid UUID length: %d", err.len) -} - -// IsInvalidLengthError is matcher function for custom error invalidLengthError -func IsInvalidLengthError(err error) bool { - _, ok := err.(invalidLengthError) - return ok -} - -// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both -// the standard UUID forms defined in RFC 4122 -// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition, -// Parse accepts non-standard strings such as the raw hex encoding -// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings, -// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are -// examined in the latter case. Parse should not be used to validate strings as -// it parses non-standard encodings as indicated above. -func Parse(s string) (UUID, error) { - var uuid UUID - switch len(s) { - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - case 36: - - // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - case 36 + 9: - if !strings.EqualFold(s[:9], "urn:uuid:") { - return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) - } - s = s[9:] - - // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} - case 36 + 2: - s = s[1:] - - // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - case 32: - var ok bool - for i := range uuid { - uuid[i], ok = xtob(s[i*2], s[i*2+1]) - if !ok { - return uuid, errors.New("invalid UUID format") - } - } - return uuid, nil - default: - return uuid, invalidLengthError{len(s)} - } - // s is now at least 36 bytes long - // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return uuid, errors.New("invalid UUID format") - } - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34, - } { - v, ok := xtob(s[x], s[x+1]) - if !ok { - return uuid, errors.New("invalid UUID format") - } - uuid[i] = v - } - return uuid, nil -} - -// ParseBytes is like Parse, except it parses a byte slice instead of a string. -func ParseBytes(b []byte) (UUID, error) { - var uuid UUID - switch len(b) { - case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) { - return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) - } - b = b[9:] - case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} - b = b[1:] - case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - var ok bool - for i := 0; i < 32; i += 2 { - uuid[i/2], ok = xtob(b[i], b[i+1]) - if !ok { - return uuid, errors.New("invalid UUID format") - } - } - return uuid, nil - default: - return uuid, invalidLengthError{len(b)} - } - // s is now at least 36 bytes long - // it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' { - return uuid, errors.New("invalid UUID format") - } - for i, x := range [16]int{ - 0, 2, 4, 6, - 9, 11, - 14, 16, - 19, 21, - 24, 26, 28, 30, 32, 34, - } { - v, ok := xtob(b[x], b[x+1]) - if !ok { - return uuid, errors.New("invalid UUID format") - } - uuid[i] = v - } - return uuid, nil -} - -// MustParse is like Parse but panics if the string cannot be parsed. -// It simplifies safe initialization of global variables holding compiled UUIDs. -func MustParse(s string) UUID { - uuid, err := Parse(s) - if err != nil { - panic(`uuid: Parse(` + s + `): ` + err.Error()) - } - return uuid -} - -// FromBytes creates a new UUID from a byte slice. Returns an error if the slice -// does not have a length of 16. The bytes are copied from the slice. -func FromBytes(b []byte) (uuid UUID, err error) { - err = uuid.UnmarshalBinary(b) - return uuid, err -} - -// Must returns uuid if err is nil and panics otherwise. -func Must(uuid UUID, err error) UUID { - if err != nil { - panic(err) - } - return uuid -} - -// Validate returns an error if s is not a properly formatted UUID in one of the following formats: -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} -// It returns an error if the format is invalid, otherwise nil. -func Validate(s string) error { - switch len(s) { - // Standard UUID format - case 36: - - // UUID with "urn:uuid:" prefix - case 36 + 9: - if !strings.EqualFold(s[:9], "urn:uuid:") { - return fmt.Errorf("invalid urn prefix: %q", s[:9]) - } - s = s[9:] - - // UUID enclosed in braces - case 36 + 2: - if s[0] != '{' || s[len(s)-1] != '}' { - return fmt.Errorf("invalid bracketed UUID format") - } - s = s[1 : len(s)-1] - - // UUID without hyphens - case 32: - for i := 0; i < len(s); i += 2 { - _, ok := xtob(s[i], s[i+1]) - if !ok { - return errors.New("invalid UUID format") - } - } - - default: - return invalidLengthError{len(s)} - } - - // Check for standard UUID format - if len(s) == 36 { - if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { - return errors.New("invalid UUID format") - } - for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { - if _, ok := xtob(s[x], s[x+1]); !ok { - return errors.New("invalid UUID format") - } - } - } - - return nil -} - -// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -// , or "" if uuid is invalid. -func (uuid UUID) String() string { - var buf [36]byte - encodeHex(buf[:], uuid) - return string(buf[:]) -} - -// URN returns the RFC 2141 URN form of uuid, -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid. -func (uuid UUID) URN() string { - var buf [36 + 9]byte - copy(buf[:], "urn:uuid:") - encodeHex(buf[9:], uuid) - return string(buf[:]) -} - -func encodeHex(dst []byte, uuid UUID) { - hex.Encode(dst, uuid[:4]) - dst[8] = '-' - hex.Encode(dst[9:13], uuid[4:6]) - dst[13] = '-' - hex.Encode(dst[14:18], uuid[6:8]) - dst[18] = '-' - hex.Encode(dst[19:23], uuid[8:10]) - dst[23] = '-' - hex.Encode(dst[24:], uuid[10:]) -} - -// Variant returns the variant encoded in uuid. -func (uuid UUID) Variant() Variant { - switch { - case (uuid[8] & 0xc0) == 0x80: - return RFC4122 - case (uuid[8] & 0xe0) == 0xc0: - return Microsoft - case (uuid[8] & 0xe0) == 0xe0: - return Future - default: - return Reserved - } -} - -// Version returns the version of uuid. -func (uuid UUID) Version() Version { - return Version(uuid[6] >> 4) -} - -func (v Version) String() string { - if v > 15 { - return fmt.Sprintf("BAD_VERSION_%d", v) - } - return fmt.Sprintf("VERSION_%d", v) -} - -func (v Variant) String() string { - switch v { - case RFC4122: - return "RFC4122" - case Reserved: - return "Reserved" - case Microsoft: - return "Microsoft" - case Future: - return "Future" - case Invalid: - return "Invalid" - } - return fmt.Sprintf("BadVariant%d", int(v)) -} - -// SetRand sets the random number generator to r, which implements io.Reader. -// If r.Read returns an error when the package requests random data then -// a panic will be issued. -// -// Calling SetRand with nil sets the random number generator to the default -// generator. -func SetRand(r io.Reader) { - if r == nil { - rander = rand.Reader - return - } - rander = r -} - -// EnableRandPool enables internal randomness pool used for Random -// (Version 4) UUID generation. The pool contains random bytes read from -// the random number generator on demand in batches. Enabling the pool -// may improve the UUID generation throughput significantly. -// -// Since the pool is stored on the Go heap, this feature may be a bad fit -// for security sensitive applications. -// -// Both EnableRandPool and DisableRandPool are not thread-safe and should -// only be called when there is no possibility that New or any other -// UUID Version 4 generation function will be called concurrently. -func EnableRandPool() { - poolEnabled = true -} - -// DisableRandPool disables the randomness pool if it was previously -// enabled with EnableRandPool. -// -// Both EnableRandPool and DisableRandPool are not thread-safe and should -// only be called when there is no possibility that New or any other -// UUID Version 4 generation function will be called concurrently. -func DisableRandPool() { - poolEnabled = false - defer poolMu.Unlock() - poolMu.Lock() - poolPos = randPoolSize -} - -// UUIDs is a slice of UUID types. -type UUIDs []UUID - -// Strings returns a string slice containing the string form of each UUID in uuids. -func (uuids UUIDs) Strings() []string { - var uuidStrs = make([]string, len(uuids)) - for i, uuid := range uuids { - uuidStrs[i] = uuid.String() - } - return uuidStrs -} diff --git a/vendor/github.com/google/uuid/version1.go b/vendor/github.com/google/uuid/version1.go deleted file mode 100644 index 4631096..0000000 --- a/vendor/github.com/google/uuid/version1.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "encoding/binary" -) - -// NewUUID returns a Version 1 UUID based on the current NodeID and clock -// sequence, and the current time. If the NodeID has not been set by SetNodeID -// or SetNodeInterface then it will be set automatically. If the NodeID cannot -// be set NewUUID returns nil. If clock sequence has not been set by -// SetClockSequence then it will be set automatically. If GetTime fails to -// return the current NewUUID returns nil and an error. -// -// In most cases, New should be used. -func NewUUID() (UUID, error) { - var uuid UUID - now, seq, err := GetTime() - if err != nil { - return uuid, err - } - - timeLow := uint32(now & 0xffffffff) - timeMid := uint16((now >> 32) & 0xffff) - timeHi := uint16((now >> 48) & 0x0fff) - timeHi |= 0x1000 // Version 1 - - binary.BigEndian.PutUint32(uuid[0:], timeLow) - binary.BigEndian.PutUint16(uuid[4:], timeMid) - binary.BigEndian.PutUint16(uuid[6:], timeHi) - binary.BigEndian.PutUint16(uuid[8:], seq) - - nodeMu.Lock() - if nodeID == zeroID { - setNodeInterface("") - } - copy(uuid[10:], nodeID[:]) - nodeMu.Unlock() - - return uuid, nil -} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go deleted file mode 100644 index 7697802..0000000 --- a/vendor/github.com/google/uuid/version4.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "io" - -// New creates a new random UUID or panics. New is equivalent to -// the expression -// -// uuid.Must(uuid.NewRandom()) -func New() UUID { - return Must(NewRandom()) -} - -// NewString creates a new random UUID and returns it as a string or panics. -// NewString is equivalent to the expression -// -// uuid.New().String() -func NewString() string { - return Must(NewRandom()).String() -} - -// NewRandom returns a Random (Version 4) UUID. -// -// The strength of the UUIDs is based on the strength of the crypto/rand -// package. -// -// Uses the randomness pool if it was enabled with EnableRandPool. -// -// A note about uniqueness derived from the UUID Wikipedia entry: -// -// Randomly generated UUIDs have 122 random bits. One's annual risk of being -// hit by a meteorite is estimated to be one chance in 17 billion, that -// means the probability is about 0.00000000006 (6 × 10−11), -// equivalent to the odds of creating a few tens of trillions of UUIDs in a -// year and having one duplicate. -func NewRandom() (UUID, error) { - if !poolEnabled { - return NewRandomFromReader(rander) - } - return newRandomFromPool() -} - -// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. -func NewRandomFromReader(r io.Reader) (UUID, error) { - var uuid UUID - _, err := io.ReadFull(r, uuid[:]) - if err != nil { - return Nil, err - } - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid, nil -} - -func newRandomFromPool() (UUID, error) { - var uuid UUID - poolMu.Lock() - if poolPos == randPoolSize { - _, err := io.ReadFull(rander, pool[:]) - if err != nil { - poolMu.Unlock() - return Nil, err - } - poolPos = 0 - } - copy(uuid[:], pool[poolPos:(poolPos+16)]) - poolPos += 16 - poolMu.Unlock() - - uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 - return uuid, nil -} diff --git a/vendor/github.com/google/uuid/version6.go b/vendor/github.com/google/uuid/version6.go deleted file mode 100644 index 339a959..0000000 --- a/vendor/github.com/google/uuid/version6.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2023 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import "encoding/binary" - -// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality. -// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs. -// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead. -// -// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6 -// -// NewV6 returns a Version 6 UUID based on the current NodeID and clock -// sequence, and the current time. If the NodeID has not been set by SetNodeID -// or SetNodeInterface then it will be set automatically. If the NodeID cannot -// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by -// SetClockSequence then it will be set automatically. If GetTime fails to -// return the current NewV6 returns Nil and an error. -func NewV6() (UUID, error) { - var uuid UUID - now, seq, err := GetTime() - if err != nil { - return uuid, err - } - - /* - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | time_high | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | time_mid | time_low_and_version | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |clk_seq_hi_res | clk_seq_low | node (0-1) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | node (2-5) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - binary.BigEndian.PutUint64(uuid[0:], uint64(now)) - binary.BigEndian.PutUint16(uuid[8:], seq) - - uuid[6] = 0x60 | (uuid[6] & 0x0F) - uuid[8] = 0x80 | (uuid[8] & 0x3F) - - nodeMu.Lock() - if nodeID == zeroID { - setNodeInterface("") - } - copy(uuid[10:], nodeID[:]) - nodeMu.Unlock() - - return uuid, nil -} diff --git a/vendor/github.com/google/uuid/version7.go b/vendor/github.com/google/uuid/version7.go deleted file mode 100644 index 3167b64..0000000 --- a/vendor/github.com/google/uuid/version7.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2023 Google Inc. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package uuid - -import ( - "io" -) - -// UUID version 7 features a time-ordered value field derived from the widely -// implemented and well known Unix Epoch timestamp source, -// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded. -// As well as improved entropy characteristics over versions 1 or 6. -// -// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7 -// -// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible. -// -// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch). -// Uses the randomness pool if it was enabled with EnableRandPool. -// On error, NewV7 returns Nil and an error -func NewV7() (UUID, error) { - uuid, err := NewRandom() - if err != nil { - return uuid, err - } - makeV7(uuid[:]) - return uuid, nil -} - -// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch). -// it use NewRandomFromReader fill random bits. -// On error, NewV7FromReader returns Nil and an error. -func NewV7FromReader(r io.Reader) (UUID, error) { - uuid, err := NewRandomFromReader(r) - if err != nil { - return uuid, err - } - - makeV7(uuid[:]) - return uuid, nil -} - -// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6]) -// uuid[8] already has the right version number (Variant is 10) -// see function NewV7 and NewV7FromReader -func makeV7(uuid []byte) { - /* - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | unix_ts_ms | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | unix_ts_ms | ver | rand_a (12 bit seq) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |var| rand_b | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | rand_b | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - _ = uuid[15] // bounds check - - t, s := getV7Time() - - uuid[0] = byte(t >> 40) - uuid[1] = byte(t >> 32) - uuid[2] = byte(t >> 24) - uuid[3] = byte(t >> 16) - uuid[4] = byte(t >> 8) - uuid[5] = byte(t) - - uuid[6] = 0x70 | (0x0F & byte(s>>8)) - uuid[7] = byte(s) -} - -// lastV7time is the last time we returned stored as: -// -// 52 bits of time in milliseconds since epoch -// 12 bits of (fractional nanoseconds) >> 8 -var lastV7time int64 - -const nanoPerMilli = 1000000 - -// getV7Time returns the time in milliseconds and nanoseconds / 256. -// The returned (milli << 12 + seq) is guarenteed to be greater than -// (milli << 12 + seq) returned by any previous call to getV7Time. -func getV7Time() (milli, seq int64) { - timeMu.Lock() - defer timeMu.Unlock() - - nano := timeNow().UnixNano() - milli = nano / nanoPerMilli - // Sequence number is between 0 and 3906 (nanoPerMilli>>8) - seq = (nano - milli*nanoPerMilli) >> 8 - now := milli<<12 + seq - if now <= lastV7time { - now = lastV7time + 1 - milli = now >> 12 - seq = now & 0xfff - } - lastV7time = now - return milli, seq -} diff --git a/vendor/modules.txt b/vendor/modules.txt index e052f21..f4992f8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,3 +1,6 @@ +# github.com/Wifx/gonetworkmanager/v2 v2.2.0 +## explicit; go 1.12 +github.com/Wifx/gonetworkmanager/v2 # github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 ## explicit; go 1.12 github.com/go-gl/gl/v3.3-core/gl @@ -8,9 +11,6 @@ github.com/go-gl/mathgl/mgl32 # github.com/godbus/dbus/v5 v5.1.0 ## explicit; go 1.12 github.com/godbus/dbus/v5 -# github.com/google/uuid v1.6.0 -## explicit -github.com/google/uuid # github.com/jinzhu/inflection v1.0.0 ## explicit github.com/jinzhu/inflection