1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-25 14:02:53 -05:00
Files
DankMaterialShell/core/internal/server/network/handlers.go
bbedward c1d57946d9 matugen: fix adw-gtk3 setting in light mode
- and add models.Get/GetOr helpers
2026-01-01 23:13:12 -05:00

590 lines
18 KiB
Go

package network
import (
"encoding/json"
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/log"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/params"
)
func HandleRequest(conn net.Conn, req models.Request, manager *Manager) {
switch req.Method {
case "network.getState":
handleGetState(conn, req, manager)
case "network.wifi.scan":
handleScanWiFi(conn, req, manager)
case "network.wifi.networks":
handleGetWiFiNetworks(conn, req, manager)
case "network.wifi.connect":
handleConnectWiFi(conn, req, manager)
case "network.wifi.disconnect":
handleDisconnectWiFi(conn, req, manager)
case "network.wifi.forget":
handleForgetWiFi(conn, req, manager)
case "network.wifi.toggle":
handleToggleWiFi(conn, req, manager)
case "network.wifi.enable":
handleEnableWiFi(conn, req, manager)
case "network.wifi.disable":
handleDisableWiFi(conn, req, manager)
case "network.ethernet.connect.config":
handleConnectEthernetSpecificConfig(conn, req, manager)
case "network.ethernet.connect":
handleConnectEthernet(conn, req, manager)
case "network.ethernet.disconnect":
handleDisconnectEthernet(conn, req, manager)
case "network.preference.set":
handleSetPreference(conn, req, manager)
case "network.info":
handleGetNetworkInfo(conn, req, manager)
case "network.ethernet.info":
handleGetWiredNetworkInfo(conn, req, manager)
case "network.subscribe":
handleSubscribe(conn, req, manager)
case "network.credentials.submit":
handleCredentialsSubmit(conn, req, manager)
case "network.credentials.cancel":
handleCredentialsCancel(conn, req, manager)
case "network.vpn.profiles":
handleListVPNProfiles(conn, req, manager)
case "network.vpn.active":
handleListActiveVPN(conn, req, manager)
case "network.vpn.connect":
handleConnectVPN(conn, req, manager)
case "network.vpn.disconnect":
handleDisconnectVPN(conn, req, manager)
case "network.vpn.disconnectAll":
handleDisconnectAllVPN(conn, req, manager)
case "network.vpn.clearCredentials":
handleClearVPNCredentials(conn, req, manager)
case "network.vpn.plugins":
handleListVPNPlugins(conn, req, manager)
case "network.vpn.import":
handleImportVPN(conn, req, manager)
case "network.vpn.getConfig":
handleGetVPNConfig(conn, req, manager)
case "network.vpn.updateConfig":
handleUpdateVPNConfig(conn, req, manager)
case "network.vpn.delete":
handleDeleteVPN(conn, req, manager)
case "network.vpn.setCredentials":
handleSetVPNCredentials(conn, req, manager)
case "network.wifi.setAutoconnect":
handleSetWiFiAutoconnect(conn, req, manager)
default:
models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
}
}
func handleCredentialsSubmit(conn net.Conn, req models.Request, manager *Manager) {
token, err := params.String(req.Params, "token")
if err != nil {
log.Warnf("handleCredentialsSubmit: missing or invalid token parameter")
models.RespondError(conn, req.ID, err.Error())
return
}
secrets, err := params.StringMap(req.Params, "secrets")
if err != nil {
log.Warnf("handleCredentialsSubmit: missing or invalid secrets parameter")
models.RespondError(conn, req.ID, err.Error())
return
}
save := params.BoolOpt(req.Params, "save", true)
if err := manager.SubmitCredentials(token, secrets, save); err != nil {
log.Warnf("handleCredentialsSubmit: failed to submit credentials: %v", err)
models.RespondError(conn, req.ID, err.Error())
return
}
log.Infof("handleCredentialsSubmit: credentials submitted successfully")
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "credentials submitted"})
}
func handleCredentialsCancel(conn net.Conn, req models.Request, manager *Manager) {
token, err := params.String(req.Params, "token")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := manager.CancelCredentials(token); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "credentials cancelled"})
}
func handleGetState(conn net.Conn, req models.Request, manager *Manager) {
models.Respond(conn, req.ID, manager.GetState())
}
func handleScanWiFi(conn net.Conn, req models.Request, manager *Manager) {
device := params.StringOpt(req.Params, "device", "")
var err error
if device != "" {
err = manager.ScanWiFiDevice(device)
} else {
err = manager.ScanWiFi()
}
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "scanning"})
}
func handleGetWiFiNetworks(conn net.Conn, req models.Request, manager *Manager) {
models.Respond(conn, req.ID, manager.GetWiFiNetworks())
}
func handleConnectWiFi(conn net.Conn, req models.Request, manager *Manager) {
ssid, err := params.String(req.Params, "ssid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
var connReq ConnectionRequest
connReq.SSID = ssid
connReq.Password = params.StringOpt(req.Params, "password", "")
connReq.Username = params.StringOpt(req.Params, "username", "")
connReq.Device = params.StringOpt(req.Params, "device", "")
if interactive, ok := models.Get[bool](req, "interactive"); ok {
connReq.Interactive = interactive
} else {
state := manager.GetState()
alreadyConnected := state.WiFiConnected && state.WiFiSSID == ssid
if alreadyConnected && connReq.Device == "" {
connReq.Interactive = false
} else {
networkInfo, err := manager.GetNetworkInfo(ssid)
isSaved := err == nil && networkInfo.Saved
if isSaved {
connReq.Interactive = false
} else if err == nil && networkInfo.Secured && connReq.Password == "" && connReq.Username == "" {
connReq.Interactive = true
}
}
}
connReq.AnonymousIdentity = params.StringOpt(req.Params, "anonymousIdentity", "")
connReq.DomainSuffixMatch = params.StringOpt(req.Params, "domainSuffixMatch", "")
connReq.EAPMethod = params.StringOpt(req.Params, "eapMethod", "")
connReq.Phase2Auth = params.StringOpt(req.Params, "phase2Auth", "")
connReq.CACertPath = params.StringOpt(req.Params, "caCertPath", "")
connReq.ClientCertPath = params.StringOpt(req.Params, "clientCertPath", "")
connReq.PrivateKeyPath = params.StringOpt(req.Params, "privateKeyPath", "")
if useSystemCACerts, ok := models.Get[bool](req, "useSystemCACerts"); ok {
connReq.UseSystemCACerts = &useSystemCACerts
}
if err := manager.ConnectWiFi(connReq); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "connecting"})
}
func handleDisconnectWiFi(conn net.Conn, req models.Request, manager *Manager) {
device := params.StringOpt(req.Params, "device", "")
var err error
if device != "" {
err = manager.DisconnectWiFiDevice(device)
} else {
err = manager.DisconnectWiFi()
}
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "disconnected"})
}
func handleForgetWiFi(conn net.Conn, req models.Request, manager *Manager) {
ssid, err := params.String(req.Params, "ssid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := manager.ForgetWiFiNetwork(ssid); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "forgotten"})
}
func handleToggleWiFi(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.ToggleWiFi(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
state := manager.GetState()
models.Respond(conn, req.ID, map[string]bool{"enabled": state.WiFiEnabled})
}
func handleEnableWiFi(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.EnableWiFi(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, map[string]bool{"enabled": true})
}
func handleDisableWiFi(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.DisableWiFi(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, map[string]bool{"enabled": false})
}
func handleConnectEthernetSpecificConfig(conn net.Conn, req models.Request, manager *Manager) {
uuid, err := params.String(req.Params, "uuid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := manager.activateConnection(uuid); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "connecting"})
}
func handleConnectEthernet(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.ConnectEthernet(); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "connecting"})
}
func handleDisconnectEthernet(conn net.Conn, req models.Request, manager *Manager) {
device := params.StringOpt(req.Params, "device", "")
var err error
if device != "" {
err = manager.DisconnectEthernetDevice(device)
} else {
err = manager.DisconnectEthernet()
}
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "disconnected"})
}
func handleSetPreference(conn net.Conn, req models.Request, manager *Manager) {
preference, err := params.String(req.Params, "preference")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := manager.SetConnectionPreference(ConnectionPreference(preference)); err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, map[string]string{"preference": preference})
}
func handleGetNetworkInfo(conn net.Conn, req models.Request, manager *Manager) {
ssid, err := params.String(req.Params, "ssid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
network, err := manager.GetNetworkInfoDetailed(ssid)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, network)
}
func handleGetWiredNetworkInfo(conn net.Conn, req models.Request, manager *Manager) {
uuid, err := params.String(req.Params, "uuid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
network, err := manager.GetWiredNetworkInfoDetailed(uuid)
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
models.Respond(conn, req.ID, network)
}
func handleSubscribe(conn net.Conn, req models.Request, manager *Manager) {
clientID := fmt.Sprintf("client-%p", conn)
stateChan := manager.Subscribe(clientID)
defer manager.Unsubscribe(clientID)
initialState := manager.GetState()
event := NetworkEvent{
Type: EventStateChanged,
Data: initialState,
}
if err := json.NewEncoder(conn).Encode(models.Response[NetworkEvent]{
ID: req.ID,
Result: &event,
}); err != nil {
return
}
for state := range stateChan {
event := NetworkEvent{
Type: EventStateChanged,
Data: state,
}
if err := json.NewEncoder(conn).Encode(models.Response[NetworkEvent]{
Result: &event,
}); err != nil {
return
}
}
}
func handleListVPNProfiles(conn net.Conn, req models.Request, manager *Manager) {
profiles, err := manager.ListVPNProfiles()
if err != nil {
log.Warnf("handleListVPNProfiles: failed to list profiles: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list VPN profiles: %v", err))
return
}
models.Respond(conn, req.ID, profiles)
}
func handleListActiveVPN(conn net.Conn, req models.Request, manager *Manager) {
active, err := manager.ListActiveVPN()
if err != nil {
log.Warnf("handleListActiveVPN: failed to list active VPNs: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list active VPNs: %v", err))
return
}
models.Respond(conn, req.ID, active)
}
func handleConnectVPN(conn net.Conn, req models.Request, manager *Manager) {
uuidOrName, ok := params.StringAlt(req.Params, "uuidOrName", "name", "uuid")
if !ok {
log.Warnf("handleConnectVPN: missing uuidOrName/name/uuid parameter")
models.RespondError(conn, req.ID, "missing 'uuidOrName', 'name', or 'uuid' parameter")
return
}
singleActive := params.BoolOpt(req.Params, "singleActive", true)
if err := manager.ConnectVPN(uuidOrName, singleActive); err != nil {
log.Warnf("handleConnectVPN: failed to connect: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to connect VPN: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN connection initiated"})
}
func handleDisconnectVPN(conn net.Conn, req models.Request, manager *Manager) {
uuidOrName, ok := params.StringAlt(req.Params, "uuidOrName", "name", "uuid")
if !ok {
log.Warnf("handleDisconnectVPN: missing uuidOrName/name/uuid parameter")
models.RespondError(conn, req.ID, "missing 'uuidOrName', 'name', or 'uuid' parameter")
return
}
if err := manager.DisconnectVPN(uuidOrName); err != nil {
log.Warnf("handleDisconnectVPN: failed to disconnect: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to disconnect VPN: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN disconnected"})
}
func handleDisconnectAllVPN(conn net.Conn, req models.Request, manager *Manager) {
if err := manager.DisconnectAllVPN(); err != nil {
log.Warnf("handleDisconnectAllVPN: failed: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to disconnect all VPNs: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "All VPNs disconnected"})
}
func handleClearVPNCredentials(conn net.Conn, req models.Request, manager *Manager) {
uuidOrName, ok := params.StringAlt(req.Params, "uuid", "name", "uuidOrName")
if !ok {
log.Warnf("handleClearVPNCredentials: missing uuidOrName/name/uuid parameter")
models.RespondError(conn, req.ID, "missing uuidOrName/name/uuid parameter")
return
}
if err := manager.ClearVPNCredentials(uuidOrName); err != nil {
log.Warnf("handleClearVPNCredentials: failed: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to clear VPN credentials: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN credentials cleared"})
}
func handleSetWiFiAutoconnect(conn net.Conn, req models.Request, manager *Manager) {
ssid, err := params.String(req.Params, "ssid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
autoconnect, err := params.Bool(req.Params, "autoconnect")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
if err := manager.SetWiFiAutoconnect(ssid, autoconnect); err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to set autoconnect: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "autoconnect updated"})
}
func handleListVPNPlugins(conn net.Conn, req models.Request, manager *Manager) {
plugins, err := manager.ListVPNPlugins()
if err != nil {
log.Warnf("handleListVPNPlugins: failed to list plugins: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list VPN plugins: %v", err))
return
}
models.Respond(conn, req.ID, plugins)
}
func handleImportVPN(conn net.Conn, req models.Request, manager *Manager) {
filePath, ok := params.StringAlt(req.Params, "file", "path")
if !ok {
models.RespondError(conn, req.ID, "missing 'file' or 'path' parameter")
return
}
name := params.StringOpt(req.Params, "name", "")
result, err := manager.ImportVPN(filePath, name)
if err != nil {
log.Warnf("handleImportVPN: failed to import: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to import VPN: %v", err))
return
}
models.Respond(conn, req.ID, result)
}
func handleGetVPNConfig(conn net.Conn, req models.Request, manager *Manager) {
uuidOrName, ok := params.StringAlt(req.Params, "uuid", "name", "uuidOrName")
if !ok {
models.RespondError(conn, req.ID, "missing 'uuid', 'name', or 'uuidOrName' parameter")
return
}
config, err := manager.GetVPNConfig(uuidOrName)
if err != nil {
log.Warnf("handleGetVPNConfig: failed to get config: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to get VPN config: %v", err))
return
}
models.Respond(conn, req.ID, config)
}
func handleUpdateVPNConfig(conn net.Conn, req models.Request, manager *Manager) {
connUUID, err := params.String(req.Params, "uuid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
updates := make(map[string]any)
if name, ok := models.Get[string](req, "name"); ok {
updates["name"] = name
}
if autoconnect, ok := models.Get[bool](req, "autoconnect"); ok {
updates["autoconnect"] = autoconnect
}
if data, ok := models.Get[map[string]any](req, "data"); ok {
updates["data"] = data
}
if len(updates) == 0 {
models.RespondError(conn, req.ID, "no updates provided")
return
}
if err := manager.UpdateVPNConfig(connUUID, updates); err != nil {
log.Warnf("handleUpdateVPNConfig: failed to update: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to update VPN config: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN config updated"})
}
func handleDeleteVPN(conn net.Conn, req models.Request, manager *Manager) {
uuidOrName, ok := params.StringAlt(req.Params, "uuid", "name", "uuidOrName")
if !ok {
models.RespondError(conn, req.ID, "missing 'uuid', 'name', or 'uuidOrName' parameter")
return
}
if err := manager.DeleteVPN(uuidOrName); err != nil {
log.Warnf("handleDeleteVPN: failed to delete: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to delete VPN: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN deleted"})
}
func handleSetVPNCredentials(conn net.Conn, req models.Request, manager *Manager) {
connUUID, err := params.String(req.Params, "uuid")
if err != nil {
models.RespondError(conn, req.ID, err.Error())
return
}
username := params.StringOpt(req.Params, "username", "")
password := params.StringOpt(req.Params, "password", "")
save := params.BoolOpt(req.Params, "save", true)
if err := manager.SetVPNCredentials(connUUID, username, password, save); err != nil {
log.Warnf("handleSetVPNCredentials: failed to set credentials: %v", err)
models.RespondError(conn, req.ID, fmt.Sprintf("failed to set VPN credentials: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{Success: true, Message: "VPN credentials set"})
}