diff --git a/server/config/config.go b/server/config/config.go index 02acdce..a16f67e 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -1,13 +1,13 @@ package config import ( + "bytes" "crypto/rand" "encoding/base64" "errors" "fmt" "log" "os" - "strings" "sync" "time" @@ -15,18 +15,6 @@ import ( "gopkg.in/yaml.v3" ) -const ( - hwVersionFile = "/etc/kvm/hw" - - gpioPower = "/sys/class/gpio/gpio503/value" - gpioPowerLED = "/sys/class/gpio/gpio504/value" - - gpioResetAlpha = "/sys/class/gpio/gpio507/value" - gpioHDDLedAlpha = "/sys/class/gpio/gpio505/value" - - gpioResetBeta = "/sys/class/gpio/gpio505/value" -) - var ( config Config once sync.Once @@ -41,68 +29,83 @@ var ( Crt: "server.crt", Key: "server.key", }, - Logger: LoggerConfig{ + Logger: Logger{ Level: "info", File: "stdout", }, Authentication: "enable", - SecretKey: generateRandomString(), } ) func GetInstance() *Config { - once.Do(read) + once.Do(initialize) return &config } -func read() { - viper.SetConfigName("server") - viper.SetConfigType("yaml") - viper.AddConfigPath("/etc/kvm/") - - if err := viper.ReadInConfig(); err != nil { +func initialize() { + if err := readByFile(); err != nil { if errors.As(err, &viper.ConfigFileNotFoundError{}) { create() - log.Println("File /etc/kvm/server.yaml not found. Create a new one with default configuration.") - } else { - log.Println("Failed to read config file /etc/kvm/server.yaml. Using default configuration.") } + + if err = readByDefault(); err != nil { + log.Fatalf("Failed to read default configuration!") + } + + log.Println("using default configuration") + } + + if err := validate(); err != nil { + log.Fatalf("Failed to validate configuration!") } if err := viper.Unmarshal(&config); err != nil { - log.Fatalf("Failed to parse configuration file /etc/kvm/server.yaml: %s", err) - } - - validate() - - if config.SecretKey == "" { - config.SecretKey = defaultConfig.SecretKey + log.Fatalf("Failed to parse configuration: %s", err) } if config.Authentication == "disable" { log.Println("NOTICE: Authentication is disabled! Please ensure your service is secure!") } - log.Println("config loaded successfully") - config.HW.Version = getHwVersion() - config.HW.GPIOPower = gpioPower - config.HW.GPIOPowerLED = gpioPowerLED - switch config.HW.Version { - case HWVersionAlpha: - config.HW.GPIOHDDLed = gpioHDDLedAlpha - config.HW.GPIOReset = gpioResetAlpha - case HWVersionBeta: - config.HW.GPIOReset = gpioResetBeta - default: - log.Fatalf("Unsupported hardware version: %s", config.HW.Version) + if config.SecretKey == "" { + config.SecretKey = generateRandomString() } + + config.Hardware = getHardware() + + log.Println("config loaded successfully") } +func readByFile() error { + viper.SetConfigName("server") + viper.SetConfigType("yaml") + viper.AddConfigPath("/etc/kvm/") + + return viper.ReadInConfig() +} + +func readByDefault() error { + data, err := yaml.Marshal(defaultConfig) + if err != nil { + log.Printf("failed to marshal default config: %s", err) + return err + } + + return viper.ReadConfig(bytes.NewBuffer(data)) +} + +// Create configuration file. func create() { + var ( + file *os.File + data []byte + err error + ) + _ = os.MkdirAll("/etc/kvm", 0o644) - file, err := os.OpenFile("/etc/kvm/server.yaml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644) + file, err = os.OpenFile("/etc/kvm/server.yaml", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o644) if err != nil { log.Printf("open config failed: %s", err) return @@ -111,37 +114,39 @@ func create() { _ = file.Close() }() - data, err := yaml.Marshal(defaultConfig) - if err != nil { + if data, err = yaml.Marshal(defaultConfig); err != nil { log.Printf("failed to marshal default config: %s", err) return } - _, err = file.Write(data) - if err != nil { + if _, err = file.Write(data); err != nil { log.Printf("failed to save config: %s", err) return } - err = file.Sync() - if err != nil { + if err = file.Sync(); err != nil { log.Printf("failed to sync config: %s", err) return } + + log.Println("create file /etc/kvm/server.yaml with default configuration") } -func validate() { - if config.Port.Http > 0 && config.Port.Https > 0 { - return +// Validate the configuration. This is to ensure compatibility with earlier versions. +func validate() error { + if viper.GetInt("port.http") > 0 && viper.GetInt("port.https") > 0 { + return nil } _ = os.Remove("/etc/kvm/server.yaml") + log.Println("delete empty configuration file") - if err := viper.Unmarshal(&config); err != nil { - log.Fatalf("Failed to read configuration file /etc/kvm/server.yaml: %v", err) - } + create() + + return readByDefault() } +// Generate random string for secret key. func generateRandomString() string { b := make([]byte, 64) _, err := rand.Read(b) @@ -153,15 +158,3 @@ func generateRandomString() string { return base64.URLEncoding.EncodeToString(b) } - -func getHwVersion() HWVersion { - content, err := os.ReadFile(hwVersionFile) - if err == nil { - version := strings.ReplaceAll(string(content), "\n", "") - if version == "beta" { - return HWVersionBeta - } - } - - return HWVersionAlpha -} diff --git a/server/config/hardware.go b/server/config/hardware.go new file mode 100644 index 0000000..e07836e --- /dev/null +++ b/server/config/hardware.go @@ -0,0 +1,70 @@ +package config + +import ( + "os" + "strings" + + log "github.com/sirupsen/logrus" +) + +type HWVersion int + +const ( + HWVersionAlpha HWVersion = iota + HWVersionBeta +) + +const ( + hwVersionFile = "/etc/kvm/hw" + + gpioPower = "/sys/class/gpio/gpio503/value" + gpioPowerLED = "/sys/class/gpio/gpio504/value" + + gpioResetAlpha = "/sys/class/gpio/gpio507/value" + gpioHDDLedAlpha = "/sys/class/gpio/gpio505/value" + + gpioResetBeta = "/sys/class/gpio/gpio505/value" +) + +func (h HWVersion) String() string { + switch h { + case HWVersionAlpha: + return "Alpha" + case HWVersionBeta: + return "Beta" + default: + return "Unknown" + } +} + +func getHwVersion() HWVersion { + content, err := os.ReadFile(hwVersionFile) + if err == nil { + version := strings.ReplaceAll(string(content), "\n", "") + if version == "beta" { + return HWVersionBeta + } + } + + return HWVersionAlpha +} + +func getHardware() Hardware { + h := Hardware{} + + h.Version = getHwVersion() + h.GPIOPower = gpioPower + h.GPIOPowerLED = gpioPowerLED + + switch h.Version { + case HWVersionAlpha: + h.GPIOHDDLed = gpioHDDLedAlpha + h.GPIOReset = gpioResetAlpha + case HWVersionBeta: + h.GPIOReset = gpioResetBeta + default: + log.Fatalf("Unsupported hardware version: %s", h.Version) + } + + return h +} diff --git a/server/config/types.go b/server/config/types.go index 9a5422b..6c0c089 100644 --- a/server/config/types.go +++ b/server/config/types.go @@ -1,43 +1,17 @@ package config -type HWVersion int - -const ( - HWVersionAlpha HWVersion = iota - HWVersionBeta -) - -func (h HWVersion) String() string { - switch h { - case HWVersionAlpha: - return "Alpha" - case HWVersionBeta: - return "Beta" - default: - return "Unknown" - } -} - type Config struct { - Protocol string `yaml:"proto"` - Port Port `yaml:"port"` - Cert Cert `yaml:"cert"` - Logger LoggerConfig `yaml:"logger"` - Authentication string `yaml:"authentication"` - SecretKey string `yaml:"secretKey"` + Protocol string `yaml:"proto"` + Port Port `yaml:"port"` + Cert Cert `yaml:"cert"` + Logger Logger `yaml:"logger"` + Authentication string `yaml:"authentication"` + SecretKey string `yaml:"secretKey"` - HW HW `yaml:"-"` + Hardware Hardware `yaml:"-"` } -type HW struct { - Version HWVersion `yaml:"-"` - GPIOReset string `yaml:"-"` - GPIOPower string `yaml:"-"` - GPIOPowerLED string `yaml:"-"` - GPIOHDDLed string `yaml:"-"` -} - -type LoggerConfig struct { +type Logger struct { Level string `yaml:"level"` File string `yaml:"file"` } @@ -51,3 +25,11 @@ type Cert struct { Crt string `yaml:"crt"` Key string `yaml:"key"` } + +type Hardware struct { + Version HWVersion `yaml:"-"` + GPIOReset string `yaml:"-"` + GPIOPower string `yaml:"-"` + GPIOPowerLED string `yaml:"-"` + GPIOHDDLed string `yaml:"-"` +} diff --git a/server/go.mod b/server/go.mod index 7c0de76..cc3a566 100644 --- a/server/go.mod +++ b/server/go.mod @@ -9,11 +9,12 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.1 github.com/gorilla/websocket v1.5.3 github.com/mervick/aes-everywhere/go/aes256 v0.0.0-20240803013625-6759956693c0 + github.com/pion/webrtc/v4 v4.0.1 github.com/rs/cors/wrapper/gin v0.0.0-20240830163046-1084d89a1692 github.com/sirupsen/logrus v1.9.3 github.com/spf13/viper v1.19.0 github.com/unrolled/secure v1.15.0 - golang.org/x/crypto v0.23.0 + golang.org/x/crypto v0.28.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -28,6 +29,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect @@ -38,6 +40,21 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pion/datachannel v1.5.9 // indirect + github.com/pion/dtls/v3 v3.0.3 // indirect + github.com/pion/ice/v4 v4.0.2 // indirect + github.com/pion/interceptor v0.1.37 // indirect + github.com/pion/logging v0.2.2 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect + github.com/pion/randutil v0.1.0 // indirect + github.com/pion/rtcp v1.2.14 // indirect + github.com/pion/rtp v1.8.9 // indirect + github.com/pion/sctp v1.8.33 // indirect + github.com/pion/sdp/v3 v3.0.9 // indirect + github.com/pion/srtp/v3 v3.0.4 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/transport/v3 v3.0.7 // indirect + github.com/pion/turn/v4 v4.0.0 // indirect github.com/rs/cors v1.11.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -48,13 +65,14 @@ require ( github.com/subosito/gotenv v1.6.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect + github.com/wlynxg/anet v0.0.3 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/server/go.sum b/server/go.sum index bcb4ae3..a34a695 100644 --- a/server/go.sum +++ b/server/go.sum @@ -37,6 +37,8 @@ github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -68,6 +70,38 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA= +github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE= +github.com/pion/dtls/v3 v3.0.3 h1:j5ajZbQwff7Z8k3pE3S+rQ4STvKvXUdKsi/07ka+OWM= +github.com/pion/dtls/v3 v3.0.3/go.mod h1:weOTUyIV4z0bQaVzKe8kpaP17+us3yAuiQsEAG1STMU= +github.com/pion/ice/v4 v4.0.2 h1:1JhBRX8iQLi0+TfcavTjPjI6GO41MFn4CeTBX+Y9h5s= +github.com/pion/ice/v4 v4.0.2/go.mod h1:DCdqyzgtsDNYN6/3U8044j3U7qsJ9KFJC92VnOWHvXg= +github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI= +github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= +github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= +github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= +github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= +github.com/pion/rtp v1.8.9 h1:E2HX740TZKaqdcPmf4pw6ZZuG8u5RlMMt+l3dxeu6Wk= +github.com/pion/rtp v1.8.9/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= +github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw= +github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM= +github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= +github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= +github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M= +github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ= +github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM= +github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA= +github.com/pion/webrtc/v4 v4.0.1 h1:6Unwc6JzoTsjxetcAIoWH81RUM4K5dBc1BbJGcF9WVE= +github.com/pion/webrtc/v4 v4.0.1/go.mod h1:SfNn8CcFxR6OUVjLXVslAQ3a3994JhyE3Hw1jAuqEto= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -113,6 +147,8 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/unrolled/secure v1.15.0 h1:q7x+pdp8jAHnbzxu6UheP8fRlG/rwYTb8TPuQ3rn9Og= github.com/unrolled/secure v1.15.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= +github.com/wlynxg/anet v0.0.3 h1:PvR53psxFXstc12jelG6f1Lv4MWqE0tI76/hHGjh9rg= +github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= @@ -120,21 +156,21 @@ go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTV golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/server/router/application.go b/server/router/application.go index 14007e7..1d59e39 100644 --- a/server/router/application.go +++ b/server/router/application.go @@ -1,15 +1,13 @@ package router import ( - "github.com/gin-gonic/gin" - log "github.com/sirupsen/logrus" - "NanoKVM-Server/middleware" "NanoKVM-Server/service/application" + + "github.com/gin-gonic/gin" ) func applicationRouter(r *gin.Engine) { - log.Debugf("application router init") service := application.NewService() api := r.Group("/api").Use(middleware.CheckToken()) @@ -17,5 +15,4 @@ func applicationRouter(r *gin.Engine) { api.POST("/application/update", service.Update) // update application api.GET("/application/lib", service.GetLib) // check if lib exists api.POST("/application/lib", service.UpdateLib) // update lib - log.Debugf("application router init done") } diff --git a/server/router/router.go b/server/router/router.go index c61e171..6bb4322 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -7,11 +7,13 @@ import ( "github.com/gin-gonic/contrib/static" "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" ) func Init(r *gin.Engine) { web(r) server(r) + log.Debugf("router init done") } func web(r *gin.Engine) { diff --git a/server/service/application/lib.go b/server/service/application/lib.go index 58a24a3..e508305 100644 --- a/server/service/application/lib.go +++ b/server/service/application/lib.go @@ -1,6 +1,8 @@ package application import ( + "NanoKVM-Server/proto" + "NanoKVM-Server/utils" "errors" "fmt" "net/http" @@ -11,9 +13,6 @@ import ( "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" - - "NanoKVM-Server/proto" - "NanoKVM-Server/utils" ) func (s *Service) GetLib(c *gin.Context) { @@ -52,7 +51,7 @@ func (s *Service) UpdateLib(c *gin.Context) { return } - err := utils.MoveFile(temporary+"/"+libName, libDir+"/") // update lib + err := utils.MoveFile(temporary+"/"+libName, libDir+"/"+libName) // update lib if err != nil { rsp.ErrRsp(c, -2, "update lib failed") return diff --git a/server/service/hid/mouse.go b/server/service/hid/mouse.go index c82d5c1..fe268c9 100644 --- a/server/service/hid/mouse.go +++ b/server/service/hid/mouse.go @@ -80,7 +80,7 @@ func (h *Hid) mouseMoveRelative(event []int) { } func (h *Hid) writeWithTimeout(file *os.File, data []byte) { - deadline := time.Now().Add(9 * time.Millisecond) + deadline := time.Now().Add(8 * time.Millisecond) _ = file.SetWriteDeadline(deadline) _, err := file.Write(data) @@ -88,7 +88,7 @@ func (h *Hid) writeWithTimeout(file *os.File, data []byte) { switch { case errors.Is(err, os.ErrClosed): log.Debugf("hid already closed, reopen it...") - h.Open() + h.OpenNoLock() case errors.Is(err, os.ErrDeadlineExceeded): log.Debugf("write to hid timeout") default: diff --git a/server/service/hid/operation.go b/server/service/hid/operation.go index d07814f..3b84e63 100644 --- a/server/service/hid/operation.go +++ b/server/service/hid/operation.go @@ -61,7 +61,7 @@ func (h *Hid) Write(file *os.File, data []byte) { if err != nil { if errors.Is(err, os.ErrClosed) { log.Debugf("hid already closed, reopen it...") - h.Open() + h.OpenNoLock() } else { log.Errorf("write to hid failed: %s", err) } diff --git a/server/service/hid/reset.go b/server/service/hid/reset.go index 5a72c9b..703448f 100644 --- a/server/service/hid/reset.go +++ b/server/service/hid/reset.go @@ -1,12 +1,11 @@ package hid import ( + "NanoKVM-Server/proto" "os" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" - - "NanoKVM-Server/proto" ) func (s *Service) Reset(c *gin.Context) { @@ -15,7 +14,7 @@ func (s *Service) Reset(c *gin.Context) { defer s.hid.kbMutex.Unlock() // reset USB - f, err := os.Open("/sys/kernel/config/usb_gadget/g0/UDC") + f, err := os.OpenFile("/sys/kernel/config/usb_gadget/g0/UDC", os.O_WRONLY, 0644) if err != nil { log.Errorf("open /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) rsp.ErrRsp(c, -1, "open usb gadget file failed") @@ -51,7 +50,7 @@ func (s *Service) Reset(c *gin.Context) { return } - f, err = os.Open("/sys/kernel/config/usb_gadget/g0/UDC") + f, err = os.OpenFile("/sys/kernel/config/usb_gadget/g0/UDC", os.O_WRONLY, 0644) if err != nil { log.Errorf("open /sys/kernel/config/usb_gadget/g0/UDC failed: %s", err) rsp.ErrRsp(c, -1, "open usb gadget file failed") diff --git a/server/service/vm/gpio.go b/server/service/vm/gpio.go index b37ee58..b9e0283 100644 --- a/server/service/vm/gpio.go +++ b/server/service/vm/gpio.go @@ -26,9 +26,9 @@ func (s *Service) SetGpio(c *gin.Context) { switch req.Type { case "power": - device = s.config.HW.GPIOPower + device = s.config.Hardware.GPIOPower case "reset": - device = s.config.HW.GPIOReset + device = s.config.Hardware.GPIOReset default: rsp.ErrRsp(c, -2, fmt.Sprintf("invalid power event: %s", req.Type)) return @@ -53,15 +53,15 @@ func (s *Service) SetGpio(c *gin.Context) { func (s *Service) GetGpio(c *gin.Context) { var rsp proto.Response - pwr, err := readGpio(s.config.HW.GPIOPowerLED) + pwr, err := readGpio(s.config.Hardware.GPIOPowerLED) if err != nil { rsp.ErrRsp(c, -2, fmt.Sprintf("failed to read power led: %s", err)) return } hdd := false - if s.config.HW.Version == config.HWVersionAlpha { - hdd, err = readGpio(s.config.HW.GPIOHDDLed) + if s.config.Hardware.Version == config.HWVersionAlpha { + hdd, err = readGpio(s.config.Hardware.GPIOHDDLed) if err != nil { rsp.ErrRsp(c, -2, fmt.Sprintf("failed to read hdd led: %s", err)) return diff --git a/server/utils/unzip.go b/server/utils/unzip.go index 922993c..bcc959e 100644 --- a/server/utils/unzip.go +++ b/server/utils/unzip.go @@ -25,7 +25,7 @@ func Unzip(filename string, dest string) error { } } else { err = unzipFile(dstPath, f) - if err == nil { + if err != nil { return err } } diff --git a/web/src/api/application.ts b/web/src/api/application.ts index d121719..1f6b451 100644 --- a/web/src/api/application.ts +++ b/web/src/api/application.ts @@ -21,5 +21,9 @@ export function getLib() { // download lib export function updateLib() { - return http.post('/api/application/lib'); + return http.request({ + method: 'post', + url: '/api/application/lib', + timeout: 15 * 60 * 1000 + }); } diff --git a/web/src/pages/desktop/lib.tsx b/web/src/pages/desktop/lib.tsx index 0ef6ecf..fcf663d 100644 --- a/web/src/pages/desktop/lib.tsx +++ b/web/src/pages/desktop/lib.tsx @@ -44,10 +44,10 @@ export const Lib = ({ setIsLoading, setTips }: LibProps) => { } }) .finally(() => { - setIsLoading(false); - setTips(''); - setTimeout(() => { + setIsLoading(false); + setTips(''); + window.location.reload(); }, 6000); }); diff --git a/web/src/pages/desktop/menu-phone/settings/update.tsx b/web/src/pages/desktop/menu-phone/settings/update.tsx index 9e0f7a8..6d316a5 100644 --- a/web/src/pages/desktop/menu-phone/settings/update.tsx +++ b/web/src/pages/desktop/menu-phone/settings/update.tsx @@ -84,13 +84,11 @@ export const Update = ({ setIsBadgeVisible }: UpdateProps) => { setErrMsg(t('update.updateFailed')); } }) - .catch(() => { - setErrMsg(t('update.updateFailed')); - }) .finally(() => { - setIsUpdating(false); - setTimeout(() => { + setIsUpdating(false); + setErrMsg(''); + window.location.reload(); }, 6000); }); diff --git a/web/src/pages/desktop/menu/settings/update.tsx b/web/src/pages/desktop/menu/settings/update.tsx index 9e0f7a8..6d316a5 100644 --- a/web/src/pages/desktop/menu/settings/update.tsx +++ b/web/src/pages/desktop/menu/settings/update.tsx @@ -84,13 +84,11 @@ export const Update = ({ setIsBadgeVisible }: UpdateProps) => { setErrMsg(t('update.updateFailed')); } }) - .catch(() => { - setErrMsg(t('update.updateFailed')); - }) .finally(() => { - setIsUpdating(false); - setTimeout(() => { + setIsUpdating(false); + setErrMsg(''); + window.location.reload(); }, 6000); });