diff --git a/#TestList.org# b/#TestList.org# deleted file mode 100644 index 028c389..0000000 --- a/#TestList.org# +++ /dev/null @@ -1,19 +0,0 @@ -* Virtual Machine Testing -To be completed after updating rhemawave-dev, deleting nixos.qcow2, and building rhemawavekiosk-dev - -- [ ] Closure builds -- [ ] VM Starts -- [ ] RadiantWave starts -- [ ] WiFi screen does NOT appear (no wifi nic in vm) -- [ ] Email Address scren appears -- [ ] I can type an email address -- [ ] I cannot submit an incomplete email -- [ ] I can submit a complete email -- [ ] License Key screen appears -- [ ] I can type a license key -- [ ] I cannot submit an incomplete license -- [ ] I can submit a complete license -- [ ] Home screen appears -- [ ] Version string is correct -- [ ] Status: Downloading files -- diff --git a/.#TestList.org b/.#TestList.org deleted file mode 120000 index 778bf34..0000000 --- a/.#TestList.org +++ /dev/null @@ -1 +0,0 @@ -nclack@muninn.28787:1782524461 \ No newline at end of file diff --git a/TestList.org b/TestList.org index 074657e..028c389 100644 --- a/TestList.org +++ b/TestList.org @@ -1,2 +1,19 @@ * Virtual Machine Testing To be completed after updating rhemawave-dev, deleting nixos.qcow2, and building rhemawavekiosk-dev + +- [ ] Closure builds +- [ ] VM Starts +- [ ] RadiantWave starts +- [ ] WiFi screen does NOT appear (no wifi nic in vm) +- [ ] Email Address scren appears +- [ ] I can type an email address +- [ ] I cannot submit an incomplete email +- [ ] I can submit a complete email +- [ ] License Key screen appears +- [ ] I can type a license key +- [ ] I cannot submit an incomplete license +- [ ] I can submit a complete license +- [ ] Home screen appears +- [ ] Version string is correct +- [ ] Status: Downloading files +- diff --git a/internal/network/network.go b/internal/network/network.go index 629aa1c..e2e3675 100644 --- a/internal/network/network.go +++ b/internal/network/network.go @@ -106,6 +106,12 @@ func ConnectToNetwork(ssid, password string) error { return fmt.Errorf("network: access point %q not found: %w", ssid, err) } + // Delete any existing profiles for this SSID before creating a new one. + // Stale/duplicate profiles cause NM to fail silently. + if err := deleteExistingConnections(ssid); err != nil { + logger.Warning("network: could not clean up old profiles for %q: %v", ssid, err) + } + security := detectSecurity(ap) settings, err := buildConnectionSettings(ssid, password, security) if err != nil { @@ -119,7 +125,41 @@ func ConnectToNetwork(ssid, password string) error { return fmt.Errorf("network: failed to connect to %q: %w", ssid, err) } - return waitForConnection(ssid, 15*time.Second) + return waitForConnection(dev, ssid, 20*time.Second) +} + +// deleteExistingConnections removes all stored NM profiles for the given SSID. +func deleteExistingConnections(ssid string) error { + s, err := gonm.NewSettings() + if err != nil { + return err + } + connections, err := s.ListConnections() + if err != nil { + return err + } + for _, conn := range connections { + cfg, err := conn.GetSettings() + if err != nil { + continue + } + wireless, ok := cfg["802-11-wireless"] + if !ok { + continue + } + rawSSID, ok := wireless["ssid"] + if !ok { + continue + } + if string(rawSSID.([]byte)) != ssid { + continue + } + logger.Debug("network: removing existing profile for %q", ssid) + if err := conn.Delete(); err != nil { + logger.Warning("network: failed to delete profile for %q: %v", ssid, err) + } + } + return nil } // ─── ForgetNetwork ──────────────────────────────────────────────────────────── @@ -473,13 +513,33 @@ func buildNetworkList(dev gonm.DeviceWireless) ([]Network, error) { return networks, nil } -func waitForConnection(ssid string, timeout time.Duration) error { +// waitForConnection waits until the wifi device reaches the Activated state, +// meaning DHCP has completed and the connection is fully up. +func waitForConnection(dev gonm.DeviceWireless, 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 + state, err := dev.GetPropertyState() + if err != nil { + time.Sleep(500 * time.Millisecond) + continue } + + // NmDeviceStateActivated = 100, fully connected with IP + if state == gonm.NmDeviceStateActivated { + // Confirm it's actually the SSID we wanted + current, err := CurrentNetwork() + if err == nil && current == ssid { + logger.Info("network: fully connected to %q", ssid) + return nil + } + } + + // NmDeviceStateFailed = 120, NmDeviceStateDisconnected = 30 + if state == gonm.NmDeviceStateFailed { + return fmt.Errorf("network: connection to %q failed (wrong password?)", ssid) + } + + logger.Debug("network: device state %d, waiting...", state) time.Sleep(500 * time.Millisecond) } return fmt.Errorf("network: timed out waiting for connection to %q", ssid)