mirror of
https://github.com/XZB-1248/Spark
synced 2025-10-13 03:33:50 +08:00
fix: incorrect disk info on unix-like os
This commit is contained in:
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ 1.17 ]
|
go-version: [ 1.18.1 ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version: [ 16.x ]
|
node-version: [ 16.x ]
|
||||||
go-version: [ 1.17 ]
|
go-version: [ 1.18.1 ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
@@ -14,55 +14,76 @@ import (
|
|||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
*ws.Conn
|
*ws.Conn
|
||||||
Secret []byte
|
secret []byte
|
||||||
|
secretHex string
|
||||||
}
|
}
|
||||||
|
|
||||||
var WSConn *Conn
|
var WSConn *Conn
|
||||||
var WSLock = sync.Mutex{}
|
var Mutex = &sync.Mutex{}
|
||||||
var HTTP = req.C().SetUserAgent(`SPARK COMMIT: ` + config.COMMIT)
|
var HTTP = CreateClient()
|
||||||
|
|
||||||
const MaxMessageSize = 32768 + 1024
|
const MaxMessageSize = 32768 + 1024
|
||||||
|
|
||||||
func SendData(data []byte, wsConn *Conn) error {
|
func CreateConn(wsConn *ws.Conn, secret []byte) *Conn {
|
||||||
WSLock.Lock()
|
return &Conn{
|
||||||
defer WSLock.Unlock()
|
Conn: wsConn,
|
||||||
|
secret: secret,
|
||||||
|
secretHex: hex.EncodeToString(secret),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateClient() *req.Client {
|
||||||
|
return req.C().SetUserAgent(`SPARK COMMIT: ` + config.COMMIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsConn *Conn) SendData(data []byte) error {
|
||||||
|
Mutex.Lock()
|
||||||
|
defer Mutex.Unlock()
|
||||||
if WSConn == nil {
|
if WSConn == nil {
|
||||||
return errors.New(`${i18n|wsClosed}`)
|
return errors.New(`${i18n|wsClosed}`)
|
||||||
}
|
}
|
||||||
wsConn.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
wsConn.SetWriteDeadline(Now.Add(5 * time.Second))
|
||||||
defer wsConn.SetWriteDeadline(time.Time{})
|
defer wsConn.SetWriteDeadline(time.Time{})
|
||||||
return wsConn.WriteMessage(ws.BinaryMessage, data)
|
return wsConn.WriteMessage(ws.BinaryMessage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendPack(pack interface{}, wsConn *Conn) error {
|
func (wsConn *Conn) SendPack(pack interface{}) error {
|
||||||
WSLock.Lock()
|
Mutex.Lock()
|
||||||
defer WSLock.Unlock()
|
defer Mutex.Unlock()
|
||||||
data, err := utils.JSON.Marshal(pack)
|
data, err := utils.JSON.Marshal(pack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data, err = utils.Encrypt(data, wsConn.Secret)
|
data, err = utils.Encrypt(data, wsConn.secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(data) > MaxMessageSize {
|
if len(data) > MaxMessageSize {
|
||||||
_, err = HTTP.R().
|
_, err = HTTP.R().
|
||||||
SetBody(data).
|
SetBody(data).
|
||||||
SetHeader(`Secret`, hex.EncodeToString(wsConn.Secret)).
|
SetHeader(`Secret`, wsConn.secretHex).
|
||||||
Send(`POST`, config.GetBaseURL(false)+`/ws`)
|
Send(`POST`, config.GetBaseURL(false)+`/ws`)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if WSConn == nil {
|
if WSConn == nil {
|
||||||
return errors.New(`${i18n|wsClosed}`)
|
return errors.New(`${i18n|wsClosed}`)
|
||||||
}
|
}
|
||||||
wsConn.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
wsConn.SetWriteDeadline(Now.Add(5 * time.Second))
|
||||||
defer wsConn.SetWriteDeadline(time.Time{})
|
defer wsConn.SetWriteDeadline(time.Time{})
|
||||||
return wsConn.WriteMessage(ws.BinaryMessage, data)
|
return wsConn.WriteMessage(ws.BinaryMessage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendCb(pack, prev modules.Packet, wsConn *Conn) error {
|
func (wsConn *Conn) SendCallback(pack, prev modules.Packet) error {
|
||||||
if len(prev.Event) > 0 {
|
if len(prev.Event) > 0 {
|
||||||
pack.Event = prev.Event
|
pack.Event = prev.Event
|
||||||
}
|
}
|
||||||
return SendPack(pack, wsConn)
|
return wsConn.SendPack(pack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsConn *Conn) GetSecret() []byte {
|
||||||
|
return wsConn.secret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wsConn *Conn) GetSecretHex() string {
|
||||||
|
return wsConn.secretHex
|
||||||
}
|
}
|
||||||
|
16
client/common/time.go
Normal file
16
client/common/time.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
var Now time.Time = time.Now()
|
||||||
|
var Unix int64 = Now.Unix()
|
||||||
|
|
||||||
|
// To prevent call time.Now().Unix() too often.
|
||||||
|
func init() {
|
||||||
|
go func() {
|
||||||
|
for now := range time.NewTicker(time.Second).C {
|
||||||
|
Now = now
|
||||||
|
Unix = now.Unix()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
@@ -26,45 +26,18 @@ var stop bool
|
|||||||
var (
|
var (
|
||||||
errNoSecretHeader = errors.New(`can not find secret header`)
|
errNoSecretHeader = errors.New(`can not find secret header`)
|
||||||
)
|
)
|
||||||
var handlers = map[string]func(pack modules.Packet, wsConn *common.Conn){
|
|
||||||
`ping`: ping,
|
|
||||||
`offline`: offline,
|
|
||||||
`lock`: lock,
|
|
||||||
`logoff`: logoff,
|
|
||||||
`hibernate`: hibernate,
|
|
||||||
`suspend`: suspend,
|
|
||||||
`restart`: restart,
|
|
||||||
`shutdown`: shutdown,
|
|
||||||
`screenshot`: screenshot,
|
|
||||||
`initTerminal`: initTerminal,
|
|
||||||
`inputTerminal`: inputTerminal,
|
|
||||||
`resizeTerminal`: resizeTerminal,
|
|
||||||
`pingTerminal`: pingTerminal,
|
|
||||||
`killTerminal`: killTerminal,
|
|
||||||
`listFiles`: listFiles,
|
|
||||||
`fetchFile`: fetchFile,
|
|
||||||
`removeFiles`: removeFiles,
|
|
||||||
`uploadFiles`: uploadFiles,
|
|
||||||
`uploadTextFile`: uploadTextFile,
|
|
||||||
`listProcesses`: listProcesses,
|
|
||||||
`killProcess`: killProcess,
|
|
||||||
`initDesktop`: initDesktop,
|
|
||||||
`pingDesktop`: pingDesktop,
|
|
||||||
`killDesktop`: killDesktop,
|
|
||||||
`getDesktop`: getDesktop,
|
|
||||||
}
|
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
for !stop {
|
for !stop {
|
||||||
var err error
|
var err error
|
||||||
if common.WSConn != nil {
|
if common.WSConn != nil {
|
||||||
common.WSLock.Lock()
|
common.Mutex.Lock()
|
||||||
common.WSConn.Close()
|
common.WSConn.Close()
|
||||||
common.WSLock.Unlock()
|
common.Mutex.Unlock()
|
||||||
}
|
}
|
||||||
common.WSLock.Lock()
|
common.Mutex.Lock()
|
||||||
common.WSConn, err = connectWS()
|
common.WSConn, err = connectWS()
|
||||||
common.WSLock.Unlock()
|
common.Mutex.Unlock()
|
||||||
if err != nil && !stop {
|
if err != nil && !stop {
|
||||||
golog.Error(`Connection error: `, err)
|
golog.Error(`Connection error: `, err)
|
||||||
<-time.After(3 * time.Second)
|
<-time.After(3 * time.Second)
|
||||||
@@ -105,7 +78,7 @@ func connectWS() (*common.Conn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &common.Conn{Conn: wsConn, Secret: secret}, nil
|
return common.CreateConn(wsConn, secret), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func reportWS(wsConn *common.Conn) error {
|
func reportWS(wsConn *common.Conn) error {
|
||||||
@@ -114,18 +87,18 @@ func reportWS(wsConn *common.Conn) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pack := modules.CommonPack{Act: `report`, Data: *device}
|
pack := modules.CommonPack{Act: `report`, Data: *device}
|
||||||
err = common.SendPack(pack, wsConn)
|
err = wsConn.SendPack(pack)
|
||||||
common.WSConn.SetWriteDeadline(time.Time{})
|
common.WSConn.SetWriteDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
common.WSConn.SetReadDeadline(time.Now().Add(5 * time.Second))
|
common.WSConn.SetReadDeadline(common.Now.Add(5 * time.Second))
|
||||||
_, data, err := common.WSConn.ReadMessage()
|
_, data, err := common.WSConn.ReadMessage()
|
||||||
common.WSConn.SetReadDeadline(time.Time{})
|
common.WSConn.SetReadDeadline(time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data, err = utils.Decrypt(data, common.WSConn.Secret)
|
data, err = utils.Decrypt(data, common.WSConn.GetSecret())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -148,7 +121,7 @@ func checkUpdate(wsConn *common.Conn) error {
|
|||||||
SetQueryParam(`os`, runtime.GOOS).
|
SetQueryParam(`os`, runtime.GOOS).
|
||||||
SetQueryParam(`arch`, runtime.GOARCH).
|
SetQueryParam(`arch`, runtime.GOARCH).
|
||||||
SetQueryParam(`commit`, config.COMMIT).
|
SetQueryParam(`commit`, config.COMMIT).
|
||||||
SetHeader(`Secret`, hex.EncodeToString(wsConn.Secret)).
|
SetHeader(`Secret`, wsConn.GetSecretHex()).
|
||||||
Send(`POST`, config.GetBaseURL(false)+`/api/client/update`)
|
Send(`POST`, config.GetBaseURL(false)+`/api/client/update`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -189,7 +162,7 @@ func handleWS(wsConn *common.Conn) error {
|
|||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
data, err = utils.Decrypt(data, wsConn.Secret)
|
data, err = utils.Decrypt(data, wsConn.GetSecret())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
errCount++
|
errCount++
|
||||||
@@ -220,7 +193,7 @@ func handleWS(wsConn *common.Conn) error {
|
|||||||
|
|
||||||
func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
func handleAct(pack modules.Packet, wsConn *common.Conn) {
|
||||||
if act, ok := handlers[pack.Act]; !ok {
|
if act, ok := handlers[pack.Act]; !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|actionNotImplemented}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|actionNotImplemented}`}, pack)
|
||||||
} else {
|
} else {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
@@ -147,17 +147,20 @@ func GetRAMInfo() (modules.IO, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetDiskInfo() (modules.IO, error) {
|
func GetDiskInfo() (modules.IO, error) {
|
||||||
|
devices := map[string]struct{}{}
|
||||||
result := modules.IO{}
|
result := modules.IO{}
|
||||||
disk.IOCounters()
|
disks, err := disk.Partitions(false)
|
||||||
disks, err := disk.Partitions(true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
for i := 0; i < len(disks); i++ {
|
for i := 0; i < len(disks); i++ {
|
||||||
stat, err := disk.Usage(disks[i].Mountpoint)
|
if _, ok := devices[disks[i].Device]; !ok {
|
||||||
if err == nil {
|
devices[disks[i].Device] = struct{}{}
|
||||||
result.Total += stat.Total
|
stat, err := disk.Usage(disks[i].Mountpoint)
|
||||||
result.Used += stat.Used
|
if err == nil {
|
||||||
|
result.Total += stat.Total
|
||||||
|
result.Used += stat.Used
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.Usage = float64(result.Used) / float64(result.Total) * 100
|
result.Usage = float64(result.Used) / float64(result.Total) * 100
|
||||||
|
@@ -12,21 +12,48 @@ import (
|
|||||||
"github.com/kataras/golog"
|
"github.com/kataras/golog"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var handlers = map[string]func(pack modules.Packet, wsConn *common.Conn){
|
||||||
|
`ping`: ping,
|
||||||
|
`offline`: offline,
|
||||||
|
`lock`: lock,
|
||||||
|
`logoff`: logoff,
|
||||||
|
`hibernate`: hibernate,
|
||||||
|
`suspend`: suspend,
|
||||||
|
`restart`: restart,
|
||||||
|
`shutdown`: shutdown,
|
||||||
|
`screenshot`: screenshot,
|
||||||
|
`initTerminal`: initTerminal,
|
||||||
|
`inputTerminal`: inputTerminal,
|
||||||
|
`resizeTerminal`: resizeTerminal,
|
||||||
|
`pingTerminal`: pingTerminal,
|
||||||
|
`killTerminal`: killTerminal,
|
||||||
|
`listFiles`: listFiles,
|
||||||
|
`fetchFile`: fetchFile,
|
||||||
|
`removeFiles`: removeFiles,
|
||||||
|
`uploadFiles`: uploadFiles,
|
||||||
|
`uploadTextFile`: uploadTextFile,
|
||||||
|
`listProcesses`: listProcesses,
|
||||||
|
`killProcess`: killProcess,
|
||||||
|
`initDesktop`: initDesktop,
|
||||||
|
`pingDesktop`: pingDesktop,
|
||||||
|
`killDesktop`: killDesktop,
|
||||||
|
`getDesktop`: getDesktop,
|
||||||
|
}
|
||||||
|
|
||||||
func ping(pack modules.Packet, wsConn *common.Conn) {
|
func ping(pack modules.Packet, wsConn *common.Conn) {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
device, err := GetPartialInfo()
|
device, err := GetPartialInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.SendPack(modules.CommonPack{Act: `setDevice`, Data: *device}, wsConn)
|
wsConn.SendPack(modules.CommonPack{Act: `setDevice`, Data: *device})
|
||||||
}
|
}
|
||||||
|
|
||||||
func offline(pack modules.Packet, wsConn *common.Conn) {
|
func offline(pack modules.Packet, wsConn *common.Conn) {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
stop = true
|
stop = true
|
||||||
wsConn.Close()
|
wsConn.Close()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@@ -35,75 +62,75 @@ func offline(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
func lock(pack modules.Packet, wsConn *common.Conn) {
|
func lock(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Lock()
|
err := basic.Lock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func logoff(pack modules.Packet, wsConn *common.Conn) {
|
func logoff(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Logoff()
|
err := basic.Logoff()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hibernate(pack modules.Packet, wsConn *common.Conn) {
|
func hibernate(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Hibernate()
|
err := basic.Hibernate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func suspend(pack modules.Packet, wsConn *common.Conn) {
|
func suspend(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Suspend()
|
err := basic.Suspend()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func restart(pack modules.Packet, wsConn *common.Conn) {
|
func restart(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Restart()
|
err := basic.Restart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func shutdown(pack modules.Packet, wsConn *common.Conn) {
|
func shutdown(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := basic.Shutdown()
|
err := basic.Shutdown()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func screenshot(pack modules.Packet, wsConn *common.Conn) {
|
func screenshot(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var bridge string
|
var bridge string
|
||||||
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
bridge = val.(string)
|
bridge = val.(string)
|
||||||
}
|
}
|
||||||
err := Screenshot.GetScreenshot(bridge)
|
err := Screenshot.GetScreenshot(bridge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initTerminal(pack modules.Packet, wsConn *common.Conn) {
|
func initTerminal(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := terminal.InitTerminal(pack)
|
err := terminal.InitTerminal(pack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Act: `initTerminal`, Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Act: `initTerminal`, Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,42 +157,42 @@ func listFiles(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
}
|
}
|
||||||
files, err := file.ListFiles(path)
|
files, err := file.ListFiles(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0, Data: smap{`files`: files}}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0, Data: smap{`files`: files}}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchFile(pack modules.Packet, wsConn *common.Conn) {
|
func fetchFile(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var path, filename, bridge string
|
var path, filename, bridge string
|
||||||
if val, ok := pack.GetData(`path`, reflect.String); !ok {
|
if val, ok := pack.GetData(`path`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
path = val.(string)
|
path = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := pack.GetData(`file`, reflect.String); !ok {
|
if val, ok := pack.GetData(`file`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
filename = val.(string)
|
filename = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
bridge = val.(string)
|
bridge = val.(string)
|
||||||
}
|
}
|
||||||
err := file.FetchFile(path, filename, bridge)
|
err := file.FetchFile(path, filename, bridge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFiles(pack modules.Packet, wsConn *common.Conn) {
|
func removeFiles(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var files []string
|
var files []string
|
||||||
if val, ok := pack.Data[`files`]; !ok {
|
if val, ok := pack.Data[`files`]; !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
slice := val.([]interface{})
|
slice := val.([]interface{})
|
||||||
@@ -176,24 +203,26 @@ func removeFiles(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := file.RemoveFiles(files)
|
err := file.RemoveFiles(files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
|
func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var start, end int64
|
var (
|
||||||
var files []string
|
start, end int64
|
||||||
var bridge string
|
files []string
|
||||||
|
bridge string
|
||||||
|
)
|
||||||
if val, ok := pack.Data[`files`]; !ok {
|
if val, ok := pack.Data[`files`]; !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
slice := val.([]interface{})
|
slice := val.([]interface{})
|
||||||
@@ -204,12 +233,12 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
bridge = val.(string)
|
bridge = val.(string)
|
||||||
@@ -225,28 +254,27 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if end > 0 && end < start {
|
if end > 0 && end < start {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidFileRange}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidFileRange}`}, pack)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := file.UploadFiles(files, bridge, start, end)
|
err := file.UploadFiles(files, bridge, start, end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func uploadTextFile(pack modules.Packet, wsConn *common.Conn) {
|
func uploadTextFile(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var path string
|
var path, bridge string
|
||||||
var bridge string
|
|
||||||
if val, ok := pack.GetData(`file`, reflect.String); !ok {
|
if val, ok := pack.GetData(`file`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
path = val.(string)
|
path = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
if val, ok := pack.GetData(`bridge`, reflect.String); !ok {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
bridge = val.(string)
|
bridge = val.(string)
|
||||||
@@ -254,41 +282,42 @@ func uploadTextFile(pack modules.Packet, wsConn *common.Conn) {
|
|||||||
err := file.UploadTextFile(path, bridge)
|
err := file.UploadTextFile(path, bridge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
golog.Error(err)
|
golog.Error(err)
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listProcesses(pack modules.Packet, wsConn *common.Conn) {
|
func listProcesses(pack modules.Packet, wsConn *common.Conn) {
|
||||||
processes, err := process.ListProcesses()
|
processes, err := process.ListProcesses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0, Data: map[string]interface{}{`processes`: processes}}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0, Data: map[string]interface{}{`processes`: processes}}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func killProcess(pack modules.Packet, wsConn *common.Conn) {
|
func killProcess(pack modules.Packet, wsConn *common.Conn) {
|
||||||
var (
|
var (
|
||||||
pid int64
|
pid int32
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if val, ok := pack.GetData(`pid`, reflect.String); ok {
|
if val, ok := pack.GetData(`pid`, reflect.Float64); !ok {
|
||||||
pid, err = strconv.ParseInt(val.(string), 10, 32)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|invalidParameter}`}, pack)
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
pid = int32(val.(float64))
|
||||||
}
|
}
|
||||||
err = process.KillProcess(int32(pid))
|
err = process.KillProcess(int32(pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
|
||||||
} else {
|
} else {
|
||||||
common.SendCb(modules.Packet{Code: 0}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Code: 0}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initDesktop(pack modules.Packet, wsConn *common.Conn) {
|
func initDesktop(pack modules.Packet, wsConn *common.Conn) {
|
||||||
err := desktop.InitDesktop(pack)
|
err := desktop.InitDesktop(pack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Act: `initDesktop`, Code: 1, Msg: err.Error()}, pack, wsConn)
|
wsConn.SendCallback(modules.Packet{Act: `initDesktop`, Code: 1, Msg: err.Error()}, pack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ package desktop
|
|||||||
import (
|
import (
|
||||||
"Spark/client/common"
|
"Spark/client/common"
|
||||||
"Spark/modules"
|
"Spark/modules"
|
||||||
|
"Spark/utils"
|
||||||
"Spark/utils/cmap"
|
"Spark/utils/cmap"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -19,7 +20,7 @@ import (
|
|||||||
|
|
||||||
type session struct {
|
type session struct {
|
||||||
lastPack int64
|
lastPack int64
|
||||||
binEvent []byte
|
rawEvent []byte
|
||||||
event string
|
event string
|
||||||
escape bool
|
escape bool
|
||||||
channel chan message
|
channel chan message
|
||||||
@@ -28,28 +29,31 @@ type session struct {
|
|||||||
type message struct {
|
type message struct {
|
||||||
t int
|
t int
|
||||||
info string
|
info string
|
||||||
data *[][]byte
|
data *[]*[]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
||||||
// | magic | op code | event id | img type | img length | x | y | width | height | image |
|
// | magic | OP code | event id | img type | img length | x | y | width | height | image |
|
||||||
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
||||||
// | 6 bytes | 1 byte | 16 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | - |
|
// | 5 bytes | 1 byte | 16 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | 2 bytes | - |
|
||||||
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
// +---------+---------+----------+----------+------------+---------+---------+---------+---------+-------+
|
||||||
|
|
||||||
// []byte{00, 22, 34, 19, 20}, magic bytes.
|
// magic:
|
||||||
|
// []byte{34, 22, 19, 17, 20}
|
||||||
|
|
||||||
// Op code:
|
// OP code:
|
||||||
// 00: first part of a frame.
|
// 00: first part of a frame
|
||||||
// 01: rest parts of a frame.
|
// 01: rest parts of a frame
|
||||||
// 02: set resolution of every frame.
|
// 02: set resolution of every frame
|
||||||
// 03: JSON string format. (Only for server).
|
// 03: JSON string (only for server)
|
||||||
|
|
||||||
// img type: 0: raw image, 1: compressed image (jpeg).
|
// img type:
|
||||||
|
// 0: raw image
|
||||||
|
// 1: compressed image (jpeg)
|
||||||
|
|
||||||
const compress = true
|
const compress = true
|
||||||
const blockSize = 64
|
const blockSize = 64
|
||||||
const imgQuality = 80
|
const imgQuality = 70
|
||||||
|
|
||||||
var lock = &sync.Mutex{}
|
var lock = &sync.Mutex{}
|
||||||
var working = false
|
var working = false
|
||||||
@@ -93,12 +97,12 @@ func worker() {
|
|||||||
if diff != nil && len(diff) > 0 {
|
if diff != nil && len(diff) > 0 {
|
||||||
prevDesktop = img
|
prevDesktop = img
|
||||||
sessions.IterCb(func(uuid string, t interface{}) bool {
|
sessions.IterCb(func(uuid string, t interface{}) bool {
|
||||||
desktopSession := t.(*session)
|
desktop := t.(*session)
|
||||||
desktopSession.lock.Lock()
|
desktop.lock.Lock()
|
||||||
if !desktopSession.escape {
|
if !desktop.escape {
|
||||||
desktopSession.channel <- message{t: 0, data: &diff}
|
desktop.channel <- message{t: 0, data: &diff}
|
||||||
}
|
}
|
||||||
desktopSession.lock.Unlock()
|
desktop.lock.Unlock()
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -117,9 +121,9 @@ func quitAll(info string) {
|
|||||||
keys := make([]string, 0)
|
keys := make([]string, 0)
|
||||||
sessions.IterCb(func(uuid string, t interface{}) bool {
|
sessions.IterCb(func(uuid string, t interface{}) bool {
|
||||||
keys = append(keys, uuid)
|
keys = append(keys, uuid)
|
||||||
desktopSession := t.(*session)
|
desktop := t.(*session)
|
||||||
desktopSession.escape = true
|
desktop.escape = true
|
||||||
desktopSession.channel <- message{t: 1, info: info}
|
desktop.channel <- message{t: 1, info: info}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
sessions.Clear()
|
sessions.Clear()
|
||||||
@@ -128,8 +132,8 @@ func quitAll(info string) {
|
|||||||
lock.Unlock()
|
lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func imageCompare(img, prev *image.RGBA, compress bool) [][]byte {
|
func imageCompare(img, prev *image.RGBA, compress bool) []*[]byte {
|
||||||
result := make([][]byte, 0)
|
result := make([]*[]byte, 0)
|
||||||
if prev == nil {
|
if prev == nil {
|
||||||
return splitFullImage(img, compress)
|
return splitFullImage(img, compress)
|
||||||
}
|
}
|
||||||
@@ -150,29 +154,24 @@ func imageCompare(img, prev *image.RGBA, compress bool) [][]byte {
|
|||||||
binary.BigEndian.PutUint16(buf[6:8], uint16(rect.Min.Y))
|
binary.BigEndian.PutUint16(buf[6:8], uint16(rect.Min.Y))
|
||||||
binary.BigEndian.PutUint16(buf[8:10], uint16(rect.Size().X))
|
binary.BigEndian.PutUint16(buf[8:10], uint16(rect.Size().X))
|
||||||
binary.BigEndian.PutUint16(buf[10:12], uint16(rect.Size().Y))
|
binary.BigEndian.PutUint16(buf[10:12], uint16(rect.Size().Y))
|
||||||
result = append(result, append(buf, block...))
|
buf = append(buf, block...)
|
||||||
|
result = append(result, &buf)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func splitFullImage(img *image.RGBA, compress bool) [][]byte {
|
func splitFullImage(img *image.RGBA, compress bool) []*[]byte {
|
||||||
if img == nil {
|
if img == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
result := make([][]byte, 0)
|
result := make([]*[]byte, 0)
|
||||||
rect := img.Bounds()
|
rect := img.Rect
|
||||||
imgWidth := rect.Dx()
|
imgWidth := rect.Dx()
|
||||||
imgHeight := rect.Dy()
|
imgHeight := rect.Dy()
|
||||||
for y := rect.Min.Y; y < rect.Max.Y; y += blockSize {
|
for y := rect.Min.Y; y < rect.Max.Y; y += blockSize {
|
||||||
|
height := utils.If(y+blockSize > imgHeight, imgHeight-y, blockSize)
|
||||||
for x := rect.Min.X; x < rect.Max.X; x += blockSize {
|
for x := rect.Min.X; x < rect.Max.X; x += blockSize {
|
||||||
width := blockSize
|
width := utils.If(x+blockSize > imgWidth, imgWidth-x, blockSize)
|
||||||
height := blockSize
|
|
||||||
if x+width > imgWidth {
|
|
||||||
width = imgWidth - x
|
|
||||||
}
|
|
||||||
if y+height > imgHeight {
|
|
||||||
height = imgHeight - y
|
|
||||||
}
|
|
||||||
block := getImageBlock(img, image.Rect(x, y, x+width, y+height), compress)
|
block := getImageBlock(img, image.Rect(x, y, x+width, y+height), compress)
|
||||||
buf := make([]byte, 12)
|
buf := make([]byte, 12)
|
||||||
if compress {
|
if compress {
|
||||||
@@ -185,7 +184,8 @@ func splitFullImage(img *image.RGBA, compress bool) [][]byte {
|
|||||||
binary.BigEndian.PutUint16(buf[6:8], uint16(y))
|
binary.BigEndian.PutUint16(buf[6:8], uint16(y))
|
||||||
binary.BigEndian.PutUint16(buf[8:10], uint16(width))
|
binary.BigEndian.PutUint16(buf[8:10], uint16(width))
|
||||||
binary.BigEndian.PutUint16(buf[10:12], uint16(height))
|
binary.BigEndian.PutUint16(buf[10:12], uint16(height))
|
||||||
result = append(result, append(buf, block...))
|
buf = append(buf, block...)
|
||||||
|
result = append(result, &buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
@@ -194,42 +194,35 @@ func splitFullImage(img *image.RGBA, compress bool) [][]byte {
|
|||||||
func getImageBlock(img *image.RGBA, rect image.Rectangle, compress bool) []byte {
|
func getImageBlock(img *image.RGBA, rect image.Rectangle, compress bool) []byte {
|
||||||
width := rect.Dx()
|
width := rect.Dx()
|
||||||
height := rect.Dy()
|
height := rect.Dy()
|
||||||
if rect.Min.X+width > img.Rect.Max.X {
|
buf := make([]byte, width*height*4)
|
||||||
width = img.Rect.Max.X - rect.Min.X
|
bufPos := 0
|
||||||
}
|
imgPos := img.PixOffset(rect.Min.X, rect.Min.Y)
|
||||||
if rect.Min.Y+height > img.Rect.Max.Y {
|
for y := 0; y < height; y++ {
|
||||||
height = img.Rect.Max.Y - rect.Min.Y
|
copy(buf[bufPos:bufPos+width*4], img.Pix[imgPos:imgPos+width*4])
|
||||||
}
|
bufPos += width * 4
|
||||||
buf := make([]byte, 0)
|
imgPos += img.Stride
|
||||||
for y := 0; y < rect.Dy(); y++ {
|
|
||||||
pos := (rect.Min.Y+y)*img.Rect.Size().X + rect.Min.X
|
|
||||||
end := pos + width
|
|
||||||
buf = append(buf, img.Pix[pos*4:end*4]...)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if !compress {
|
if !compress {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
newRect := image.Rect(0, 0, width, height)
|
subImg := &image.RGBA{
|
||||||
newImg := image.NewRGBA(newRect)
|
Pix: buf,
|
||||||
copy(newImg.Pix[:len(buf)], buf[:])
|
Stride: width * 4,
|
||||||
|
Rect: image.Rect(0, 0, width, height),
|
||||||
|
}
|
||||||
writer := new(bytes.Buffer)
|
writer := new(bytes.Buffer)
|
||||||
jpeg.Encode(writer, newImg, &jpeg.Options{Quality: imgQuality})
|
jpeg.Encode(writer, subImg, &jpeg.Options{Quality: imgQuality})
|
||||||
return writer.Bytes()
|
return writer.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDiff(img, prev *image.RGBA) []image.Rectangle {
|
func getDiff(img, prev *image.RGBA) []image.Rectangle {
|
||||||
|
imgWidth := img.Rect.Dx()
|
||||||
|
imgHeight := img.Rect.Dy()
|
||||||
result := make([]image.Rectangle, 0)
|
result := make([]image.Rectangle, 0)
|
||||||
for y := 0; y < img.Rect.Size().Y; y += blockSize {
|
for y := 0; y < imgHeight; y += blockSize {
|
||||||
for x := 0; x < img.Rect.Size().X; x += blockSize {
|
height := utils.If(y+blockSize > imgHeight, imgHeight-y, blockSize)
|
||||||
width := blockSize
|
for x := 0; x < imgWidth; x += blockSize {
|
||||||
height := blockSize
|
width := utils.If(x+blockSize > imgWidth, imgWidth-x, blockSize)
|
||||||
if x+width > img.Rect.Size().X {
|
|
||||||
width = img.Rect.Size().X - x
|
|
||||||
}
|
|
||||||
if y+height > img.Rect.Size().Y {
|
|
||||||
height = img.Rect.Size().Y - y
|
|
||||||
}
|
|
||||||
rect := image.Rect(x, y, x+width, y+height)
|
rect := image.Rect(x, y, x+width, y+height)
|
||||||
if isDiff(img, prev, rect) {
|
if isDiff(img, prev, rect) {
|
||||||
result = append(result, rect)
|
result = append(result, rect)
|
||||||
@@ -244,8 +237,8 @@ func isDiff(img, prev *image.RGBA, rect image.Rectangle) bool {
|
|||||||
prevHeader := (*reflect.SliceHeader)(unsafe.Pointer(&prev.Pix))
|
prevHeader := (*reflect.SliceHeader)(unsafe.Pointer(&prev.Pix))
|
||||||
imgPtr := imgHeader.Data
|
imgPtr := imgHeader.Data
|
||||||
prevPtr := prevHeader.Data
|
prevPtr := prevHeader.Data
|
||||||
imgWidth := img.Rect.Size().X
|
imgWidth := img.Rect.Dx()
|
||||||
rectWidth := rect.Size().X
|
rectWidth := rect.Dx()
|
||||||
|
|
||||||
end := 0
|
end := 0
|
||||||
if rect.Max.Y == 0 {
|
if rect.Max.Y == 0 {
|
||||||
@@ -281,139 +274,141 @@ func isDiff(img, prev *image.RGBA, rect image.Rectangle) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func InitDesktop(pack modules.Packet) error {
|
func InitDesktop(pack modules.Packet) error {
|
||||||
var desktop string
|
var uuid string
|
||||||
binEvent, err := hex.DecodeString(pack.Event)
|
rawEvent, err := hex.DecodeString(pack.Event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
||||||
return errors.New(`${i18n|invalidParameter}`)
|
return errors.New(`${i18n|invalidParameter}`)
|
||||||
} else {
|
} else {
|
||||||
desktop = val.(string)
|
uuid = val.(string)
|
||||||
}
|
}
|
||||||
desktopSession := &session{
|
desktop := &session{
|
||||||
event: pack.Event,
|
event: pack.Event,
|
||||||
binEvent: binEvent,
|
rawEvent: rawEvent,
|
||||||
lastPack: time.Now().Unix(),
|
lastPack: time.Now().Unix(),
|
||||||
escape: false,
|
escape: false,
|
||||||
channel: make(chan message, 4),
|
channel: make(chan message, 4),
|
||||||
lock: &sync.Mutex{},
|
lock: &sync.Mutex{},
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// set resolution of desktop.
|
// set resolution of desktop
|
||||||
if screenshot.NumActiveDisplays() == 0 {
|
if screenshot.NumActiveDisplays() == 0 {
|
||||||
common.SendCb(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|noDisplayFound}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|noDisplayFound}`}, pack)
|
||||||
return errors.New(`${i18n|noDisplayFound}`)
|
return errors.New(`${i18n|noDisplayFound}`)
|
||||||
}
|
}
|
||||||
buf := append([]byte{00, 22, 34, 19, 20, 02}, binEvent...)
|
buf := append([]byte{34, 22, 19, 17, 20, 02}, rawEvent...)
|
||||||
data := make([]byte, 4)
|
data := make([]byte, 4)
|
||||||
rect := screenshot.GetDisplayBounds(0)
|
rect := screenshot.GetDisplayBounds(0)
|
||||||
binary.BigEndian.PutUint16(data[:2], uint16(rect.Dx()))
|
binary.BigEndian.PutUint16(data[:2], uint16(rect.Dx()))
|
||||||
binary.BigEndian.PutUint16(data[2:], uint16(rect.Dy()))
|
binary.BigEndian.PutUint16(data[2:], uint16(rect.Dy()))
|
||||||
buf = append(buf, data...)
|
buf = append(buf, data...)
|
||||||
common.SendData(buf, common.WSConn)
|
common.WSConn.SendData(buf)
|
||||||
}
|
}
|
||||||
go func() {
|
go handleDesktop(pack, uuid, desktop)
|
||||||
for !desktopSession.escape {
|
|
||||||
select {
|
|
||||||
case msg, ok := <-desktopSession.channel:
|
|
||||||
// send error info
|
|
||||||
if msg.t == 1 || !ok {
|
|
||||||
common.SendCb(modules.Packet{Act: `quitDesktop`, Msg: msg.info}, pack, common.WSConn)
|
|
||||||
desktopSession.escape = true
|
|
||||||
sessions.Remove(desktop)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// send image
|
|
||||||
if msg.t == 0 {
|
|
||||||
buf := append([]byte{00, 22, 34, 19, 20, 00}, binEvent...)
|
|
||||||
for _, slice := range *msg.data {
|
|
||||||
if len(buf)+len(slice) >= common.MaxMessageSize {
|
|
||||||
if common.SendData(buf, common.WSConn) != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf = append([]byte{00, 22, 34, 19, 20, 01}, binEvent...)
|
|
||||||
}
|
|
||||||
buf = append(buf, slice...)
|
|
||||||
}
|
|
||||||
common.SendData(buf, common.WSConn)
|
|
||||||
buf = nil
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
case <-time.After(time.Second * 5):
|
|
||||||
default:
|
|
||||||
time.Sleep(50 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if !working {
|
if !working {
|
||||||
sessions.Set(desktop, desktopSession)
|
sessions.Set(uuid, desktop)
|
||||||
go worker()
|
go worker()
|
||||||
} else {
|
} else {
|
||||||
img := splitFullImage(prevDesktop, compress)
|
img := splitFullImage(prevDesktop, compress)
|
||||||
desktopSession.lock.Lock()
|
desktop.lock.Lock()
|
||||||
desktopSession.channel <- message{t: 0, data: &img}
|
desktop.channel <- message{t: 0, data: &img}
|
||||||
desktopSession.lock.Unlock()
|
desktop.lock.Unlock()
|
||||||
sessions.Set(desktop, desktopSession)
|
sessions.Set(uuid, desktop)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func PingDesktop(pack modules.Packet) {
|
func PingDesktop(pack modules.Packet) {
|
||||||
var desktop string
|
var uuid string
|
||||||
var desktopSession *session
|
var desktop *session
|
||||||
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktop = val.(string)
|
uuid = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := sessions.Get(desktop); !ok {
|
if val, ok := sessions.Get(uuid); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktopSession = val.(*session)
|
desktop = val.(*session)
|
||||||
desktopSession.lastPack = time.Now().Unix()
|
desktop.lastPack = time.Now().Unix()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func KillDesktop(pack modules.Packet) {
|
func KillDesktop(pack modules.Packet) {
|
||||||
var desktop string
|
var uuid string
|
||||||
var desktopSession *session
|
var desktop *session
|
||||||
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktop = val.(string)
|
uuid = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := sessions.Get(desktop); !ok {
|
if val, ok := sessions.Get(uuid); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktopSession = val.(*session)
|
desktop = val.(*session)
|
||||||
}
|
}
|
||||||
sessions.Remove(desktop)
|
sessions.Remove(uuid)
|
||||||
desktopSession.lock.Lock()
|
desktop.lock.Lock()
|
||||||
desktopSession.escape = true
|
desktop.escape = true
|
||||||
desktopSession.binEvent = nil
|
desktop.rawEvent = nil
|
||||||
desktopSession.lock.Unlock()
|
desktop.lock.Unlock()
|
||||||
common.SendCb(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|desktopSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitDesktop`, Msg: `${i18n|desktopClosed}`}, pack)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDesktop(pack modules.Packet) {
|
func GetDesktop(pack modules.Packet) {
|
||||||
var desktop string
|
var uuid string
|
||||||
var desktopSession *session
|
var desktop *session
|
||||||
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
if val, ok := pack.GetData(`desktop`, reflect.String); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktop = val.(string)
|
uuid = val.(string)
|
||||||
}
|
}
|
||||||
if val, ok := sessions.Get(desktop); !ok {
|
if val, ok := sessions.Get(uuid); !ok {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
desktopSession = val.(*session)
|
desktop = val.(*session)
|
||||||
}
|
}
|
||||||
if !desktopSession.escape {
|
if !desktop.escape {
|
||||||
img := splitFullImage(prevDesktop, compress)
|
img := splitFullImage(prevDesktop, compress)
|
||||||
desktopSession.lock.Lock()
|
desktop.lock.Lock()
|
||||||
desktopSession.channel <- message{t: 0, data: &img}
|
desktop.channel <- message{t: 0, data: &img}
|
||||||
desktopSession.lock.Unlock()
|
desktop.lock.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleDesktop(pack modules.Packet, uuid string, desktop *session) {
|
||||||
|
for !desktop.escape {
|
||||||
|
select {
|
||||||
|
case msg, ok := <-desktop.channel:
|
||||||
|
// send error info
|
||||||
|
if msg.t == 1 || !ok {
|
||||||
|
common.WSConn.SendCallback(modules.Packet{Act: `quitDesktop`, Msg: msg.info}, pack)
|
||||||
|
desktop.escape = true
|
||||||
|
sessions.Remove(uuid)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// send image
|
||||||
|
if msg.t == 0 {
|
||||||
|
buf := append([]byte{34, 22, 19, 17, 20, 00}, desktop.rawEvent...)
|
||||||
|
for _, slice := range *msg.data {
|
||||||
|
if len(buf)+len(*slice) >= common.MaxMessageSize {
|
||||||
|
if common.WSConn.SendData(buf) != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf = append([]byte{34, 22, 19, 17, 20, 01}, desktop.rawEvent...)
|
||||||
|
}
|
||||||
|
buf = append(buf, *slice...)
|
||||||
|
}
|
||||||
|
common.WSConn.SendData(buf)
|
||||||
|
buf = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case <-time.After(time.Second * 5):
|
||||||
|
default:
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,8 +419,8 @@ func healthCheck() {
|
|||||||
// stores sessions to be disconnected
|
// stores sessions to be disconnected
|
||||||
keys := make([]string, 0)
|
keys := make([]string, 0)
|
||||||
sessions.IterCb(func(uuid string, t interface{}) bool {
|
sessions.IterCb(func(uuid string, t interface{}) bool {
|
||||||
desktopSession := t.(*session)
|
desktop := t.(*session)
|
||||||
if timestamp-desktopSession.lastPack > MaxInterval {
|
if timestamp-desktop.lastPack > MaxInterval {
|
||||||
keys = append(keys, uuid)
|
keys = append(keys, uuid)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@@ -33,7 +33,7 @@ func InitTerminal(pack modules.Packet) error {
|
|||||||
termSession := &terminal{
|
termSession := &terminal{
|
||||||
pty: ptySession,
|
pty: ptySession,
|
||||||
event: pack.Event,
|
event: pack.Event,
|
||||||
lastPack: time.Now().Unix(),
|
lastPack: common.Unix,
|
||||||
}
|
}
|
||||||
terminals.Set(pack.Data[`terminal`].(string), termSession)
|
terminals.Set(pack.Data[`terminal`].(string), termSession)
|
||||||
go func() {
|
go func() {
|
||||||
@@ -41,12 +41,12 @@ func InitTerminal(pack modules.Packet) error {
|
|||||||
buffer := make([]byte, 512)
|
buffer := make([]byte, 512)
|
||||||
n, err := ptySession.Read(buffer)
|
n, err := ptySession.Read(buffer)
|
||||||
buffer = buffer[:n]
|
buffer = buffer[:n]
|
||||||
common.SendCb(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
|
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
|
||||||
`output`: hex.EncodeToString(buffer),
|
`output`: hex.EncodeToString(buffer),
|
||||||
}}, pack, common.WSConn)
|
}}, pack)
|
||||||
termSession.lastPack = time.Now().Unix()
|
termSession.lastPack = common.Unix
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`}, pack)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,12 +72,12 @@ func InputTerminal(pack modules.Packet) error {
|
|||||||
termUUID := val.(string)
|
termUUID := val.(string)
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal := val.(*terminal)
|
terminal := val.(*terminal)
|
||||||
terminal.pty.Write(data)
|
terminal.pty.Write(data)
|
||||||
terminal.lastPack = time.Now().Unix()
|
terminal.lastPack = common.Unix
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ func ResizeTerminal(pack modules.Packet) error {
|
|||||||
termUUID := val.(string)
|
termUUID := val.(string)
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal := val.(*terminal)
|
terminal := val.(*terminal)
|
||||||
@@ -119,7 +119,7 @@ func KillTerminal(pack modules.Packet) error {
|
|||||||
termUUID := val.(string)
|
termUUID := val.(string)
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal := val.(*terminal)
|
terminal := val.(*terminal)
|
||||||
@@ -140,7 +140,7 @@ func PingTerminal(pack modules.Packet) {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
termSession = val.(*terminal)
|
termSession = val.(*terminal)
|
||||||
termSession.lastPack = time.Now().Unix()
|
termSession.lastPack = common.Unix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,7 +53,7 @@ func InitTerminal(pack modules.Packet) error {
|
|||||||
stdout: &stdout,
|
stdout: &stdout,
|
||||||
stderr: &stderr,
|
stderr: &stderr,
|
||||||
stdin: &stdin,
|
stdin: &stdin,
|
||||||
lastPack: time.Now().Unix(),
|
lastPack: common.Unix,
|
||||||
}
|
}
|
||||||
terminals.Set(pack.Data[`terminal`].(string), termSession)
|
terminals.Set(pack.Data[`terminal`].(string), termSession)
|
||||||
|
|
||||||
@@ -63,18 +63,18 @@ func InitTerminal(pack modules.Packet) error {
|
|||||||
n, err := rc.Read(buffer)
|
n, err := rc.Read(buffer)
|
||||||
buffer = buffer[:n]
|
buffer = buffer[:n]
|
||||||
|
|
||||||
// Clear screen.
|
// clear screen
|
||||||
if len(buffer) == 1 && buffer[0] == 12 {
|
if len(buffer) == 1 && buffer[0] == 12 {
|
||||||
buffer = []byte{27, 91, 72, 27, 91, 50, 74}
|
buffer = []byte{27, 91, 72, 27, 91, 50, 74}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer, _ = encodeUTF8(buffer)
|
buffer, _ = encodeUTF8(buffer)
|
||||||
common.SendCb(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
|
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
|
||||||
`output`: hex.EncodeToString(buffer),
|
`output`: hex.EncodeToString(buffer),
|
||||||
}}, pack, common.WSConn)
|
}}, pack)
|
||||||
termSession.lastPack = time.Now().Unix()
|
termSession.lastPack = common.Unix
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`}, pack)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@ func InputTerminal(pack modules.Packet) error {
|
|||||||
termUUID := val.(string)
|
termUUID := val.(string)
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal := val.(*terminal)
|
terminal := val.(*terminal)
|
||||||
@@ -113,7 +113,7 @@ func InputTerminal(pack modules.Packet) error {
|
|||||||
}
|
}
|
||||||
data, _ = decodeUTF8(data)
|
data, _ = decodeUTF8(data)
|
||||||
(*terminal.stdin).Write(data)
|
(*terminal.stdin).Write(data)
|
||||||
terminal.lastPack = time.Now().Unix()
|
terminal.lastPack = common.Unix
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ func KillTerminal(pack modules.Packet) error {
|
|||||||
termUUID := val.(string)
|
termUUID := val.(string)
|
||||||
val, ok = terminals.Get(termUUID)
|
val, ok = terminals.Get(termUUID)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.SendCb(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack, common.WSConn)
|
common.WSConn.SendCallback(modules.Packet{Act: `quitTerminal`, Msg: `${i18n|terminalSessionClosed}`}, pack)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal := val.(*terminal)
|
terminal := val.(*terminal)
|
||||||
@@ -150,7 +150,7 @@ func PingTerminal(pack modules.Packet) {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
termSession = val.(*terminal)
|
termSession = val.(*terminal)
|
||||||
termSession.lastPack = time.Now().Unix()
|
termSession.lastPack = common.Unix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module Spark
|
module Spark
|
||||||
|
|
||||||
go 1.17
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/creack/pty v1.1.18
|
github.com/creack/pty v1.1.18
|
||||||
|
@@ -11,9 +11,7 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var Melody = melody.New()
|
var Melody = melody.New()
|
||||||
@@ -187,23 +185,3 @@ func DecAES(data []byte, key []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
return decBuffer[:dataLen-16], nil
|
return decBuffer[:dataLen-16], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveBytesPrefix(data *[]byte, n int) *[]byte {
|
|
||||||
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(data))
|
|
||||||
header := &reflect.SliceHeader{
|
|
||||||
Data: sliceHeader.Data + uintptr(n),
|
|
||||||
Len: sliceHeader.Len - n,
|
|
||||||
Cap: sliceHeader.Cap - n,
|
|
||||||
}
|
|
||||||
return (*[]byte)(unsafe.Pointer(header))
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveBytesSuffix(data *[]byte, n int) *[]byte {
|
|
||||||
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(data))
|
|
||||||
header := &reflect.SliceHeader{
|
|
||||||
Data: sliceHeader.Data,
|
|
||||||
Len: sliceHeader.Len - n,
|
|
||||||
Cap: sliceHeader.Cap - n,
|
|
||||||
}
|
|
||||||
return (*[]byte)(unsafe.Pointer(header))
|
|
||||||
}
|
|
||||||
|
@@ -8,7 +8,6 @@ import (
|
|||||||
"Spark/utils/melody"
|
"Spark/utils/melody"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ func KillDeviceProcess(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
trigger := utils.GetStrUUID()
|
trigger := utils.GetStrUUID()
|
||||||
common.SendPackByUUID(modules.Packet{Code: 0, Act: `killProcess`, Data: gin.H{`pid`: strconv.FormatInt(int64(form.Pid), 10)}, Event: trigger}, target)
|
common.SendPackByUUID(modules.Packet{Code: 0, Act: `killProcess`, Data: gin.H{`pid`: form.Pid}, Event: trigger}, target)
|
||||||
ok = common.AddEventOnce(func(p modules.Packet, _ *melody.Session) {
|
ok = common.AddEventOnce(func(p modules.Packet, _ *melody.Session) {
|
||||||
if p.Code != 0 {
|
if p.Code != 0 {
|
||||||
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: p.Msg})
|
ctx.AbortWithStatusJSON(http.StatusInternalServerError, modules.Packet{Code: 1, Msg: p.Msg})
|
||||||
|
@@ -178,14 +178,15 @@ func wsOnMessageBinary(session *melody.Session, data []byte) {
|
|||||||
var pack modules.Packet
|
var pack modules.Packet
|
||||||
|
|
||||||
{
|
{
|
||||||
if len(data) >= 22 {
|
dataLen := len(data)
|
||||||
if bytes.Equal(data[:5], []byte{00, 22, 34, 19, 20}) {
|
if dataLen >= 22 {
|
||||||
|
if bytes.Equal(data[:5], []byte{34, 22, 19, 17, 20}) {
|
||||||
event := hex.EncodeToString(data[6:22])
|
event := hex.EncodeToString(data[6:22])
|
||||||
copy(data[6:], data[22:])
|
copy(data[6:], data[22:])
|
||||||
common.CallEvent(modules.Packet{
|
common.CallEvent(modules.Packet{
|
||||||
Event: event,
|
Event: event,
|
||||||
Data: gin.H{
|
Data: gin.H{
|
||||||
`data`: common.RemoveBytesSuffix(&data, 16),
|
`data`: utils.GetSlicePrefix(&data, dataLen-16),
|
||||||
},
|
},
|
||||||
}, session)
|
}, session)
|
||||||
return
|
return
|
||||||
@@ -205,7 +206,7 @@ func wsOnMessageBinary(session *melody.Session, data []byte) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !common.Devices.Has(session.UUID) {
|
if !common.Devices.Has(session.UUID) {
|
||||||
session.CloseWithMsg(melody.FormatCloseMessage(1001, `invalid identifier`))
|
session.CloseWithMsg(melody.FormatCloseMessage(1001, `invalid device id`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
common.CallEvent(pack, session)
|
common.CallEvent(pack, session)
|
||||||
|
@@ -9,6 +9,8 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -17,6 +19,27 @@ var (
|
|||||||
JSON = jsoniter.ConfigCompatibleWithStandardLibrary
|
JSON = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func If[T any](b bool, t, f T) T {
|
||||||
|
if b {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func Min[T int | int32 | int64 | uint | uint32 | uint64 | float32 | float64](a, b T) T {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func Max[T int | int32 | int64 | uint | uint32 | uint64 | float32 | float64](a, b T) T {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func GenRandByte(n int) []byte {
|
func GenRandByte(n int) []byte {
|
||||||
secBuffer := make([]byte, n)
|
secBuffer := make([]byte, n)
|
||||||
rand.Reader.Read(secBuffer)
|
rand.Reader.Read(secBuffer)
|
||||||
@@ -83,3 +106,30 @@ func Decrypt(data []byte, key []byte) ([]byte, error) {
|
|||||||
//fmt.Println(`Recv: `, string(decBuffer[:dataLen-16-64]))
|
//fmt.Println(`Recv: `, string(decBuffer[:dataLen-16-64]))
|
||||||
return decBuffer, nil
|
return decBuffer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSlicePrefix[T any](data *[]T, n int) *[]T {
|
||||||
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(data))
|
||||||
|
return (*[]T)(unsafe.Pointer(&reflect.SliceHeader{
|
||||||
|
Data: sliceHeader.Data,
|
||||||
|
Len: n,
|
||||||
|
Cap: n,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSliceSuffix[T any](data *[]T, n int) *[]T {
|
||||||
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(data))
|
||||||
|
return (*[]T)(unsafe.Pointer(&reflect.SliceHeader{
|
||||||
|
Data: sliceHeader.Data + uintptr(sliceHeader.Len-n),
|
||||||
|
Len: n,
|
||||||
|
Cap: n,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSliceChunk[T any](data *[]T, start, end int) *[]T {
|
||||||
|
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(data))
|
||||||
|
return (*[]T)(unsafe.Pointer(&reflect.SliceHeader{
|
||||||
|
Data: sliceHeader.Data + uintptr(start),
|
||||||
|
Len: end - start,
|
||||||
|
Cap: end - start,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
@@ -142,6 +142,7 @@ function ScreenModal(props) {
|
|||||||
updateImage(ab.slice(offset, offset + len + 12), canvasCtx);
|
updateImage(ab.slice(offset, offset + len + 12), canvasCtx);
|
||||||
offset += len + 12;
|
offset += len + 12;
|
||||||
}
|
}
|
||||||
|
dv = null;
|
||||||
}
|
}
|
||||||
function updateImage(ab, canvasCtx) {
|
function updateImage(ab, canvasCtx) {
|
||||||
let dv = new DataView(ab);
|
let dv = new DataView(ab);
|
||||||
@@ -153,12 +154,13 @@ function ScreenModal(props) {
|
|||||||
let bh = dv.getUint16(10, false);
|
let bh = dv.getUint16(10, false);
|
||||||
ab = ab.slice(12);
|
ab = ab.slice(12);
|
||||||
if (it === 0) {
|
if (it === 0) {
|
||||||
canvasCtx.putImageData(new ImageData(new Uint8ClampedArray(ab), bw, bh), dx, dy);
|
canvasCtx.putImageData(new ImageData(new Uint8ClampedArray(ab), bw, bh), dx, dy, 0, 0, bw, bh);
|
||||||
|
dv = null;
|
||||||
} else {
|
} else {
|
||||||
createImageBitmap(new Blob([ab]), 0, 0, bw, bh)
|
createImageBitmap(new Blob([ab]), 0, 0, bw, bh)
|
||||||
.then((ib) => {
|
.then((ib) => {
|
||||||
canvasCtx.drawImage(ib, dx, dy);
|
canvasCtx.drawImage(ib, 0, 0, bw, bh, dx, dy, bw, bh);
|
||||||
});
|
}).finally(() => dv = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleJSON(ab) {
|
function handleJSON(ab) {
|
||||||
|
Reference in New Issue
Block a user