Skip to content

Commit

Permalink
optimize: terminal for Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
XZB-1248 committed Sep 20, 2022
1 parent bc63722 commit f69822b
Show file tree
Hide file tree
Showing 18 changed files with 110 additions and 114 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
## v0.1.5

* Optimize: performance of desktop viewer on Windows.
* Optimize: terminal for Windows.
* Remove: deprecated ioutil package.

* 优化:Windows下的远程桌面性能表现。
* 优化:Windows的终端表现。
* 移除:已经废弃的ioutil包。


Expand Down Expand Up @@ -112,7 +114,7 @@
* 新增:服务端和客户端已支持macOS系统。
* 新增:macOS现在将支持关机和重启功能(需要root权限)。
* 更新:类unix系统的终端现已改用pty实现,以提供完整的终端功能。
* 更新:改进了windows下的终端表现,修复了一些bug。
* 更新:改进了Windows下的终端表现,修复了一些bug。



Expand Down
2 changes: 1 addition & 1 deletion client/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (wsConn *Conn) SendData(data []byte) error {
return wsConn.WriteMessage(ws.BinaryMessage, data)
}

func (wsConn *Conn) SendPack(pack interface{}) error {
func (wsConn *Conn) SendPack(pack any) error {
Mutex.Lock()
defer Mutex.Unlock()
data, err := utils.JSON.Marshal(pack)
Expand Down
2 changes: 1 addition & 1 deletion client/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
)

// simplified type of map
type smap map[string]interface{}
type smap map[string]any

var stop bool
var (
Expand Down
6 changes: 3 additions & 3 deletions client/core/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func removeFiles(pack modules.Packet, wsConn *common.Conn) {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
return
} else {
slice := val.([]interface{})
slice := val.([]any)
for i := 0; i < len(slice); i++ {
file, ok := slice[i].(string)
if ok {
Expand Down Expand Up @@ -225,7 +225,7 @@ func uploadFiles(pack modules.Packet, wsConn *common.Conn) {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: `${i18n|fileOrDirNotExist}`}, pack)
return
} else {
slice := val.([]interface{})
slice := val.([]any)
for i := 0; i < len(slice); i++ {
file, ok := slice[i].(string)
if ok {
Expand Down Expand Up @@ -291,7 +291,7 @@ func listProcesses(pack modules.Packet, wsConn *common.Conn) {
if err != nil {
wsConn.SendCallback(modules.Packet{Code: 1, Msg: err.Error()}, pack)
} else {
wsConn.SendCallback(modules.Packet{Code: 0, Data: map[string]interface{}{`processes`: processes}}, pack)
wsConn.SendCallback(modules.Packet{Code: 0, Data: map[string]any{`processes`: processes}}, pack)
}
}

Expand Down
8 changes: 4 additions & 4 deletions client/service/desktop/desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ var lock = &sync.Mutex{}
var working = false
var sessions = cmap.New()
var prevDesktop *image.RGBA
var ErrNoImage = errors.New("no image yet")
var ErrNoImage = errors.New(`no image yet`)

func init() {
go healthCheck()
Expand Down Expand Up @@ -108,7 +108,7 @@ func worker() {
diff := imageCompare(img, prevDesktop, compress)
if diff != nil && len(diff) > 0 {
prevDesktop = img
sessions.IterCb(func(uuid string, t interface{}) bool {
sessions.IterCb(func(uuid string, t any) bool {
desktop := t.(*session)
desktop.lock.Lock()
if !desktop.escape {
Expand All @@ -134,7 +134,7 @@ func worker() {

func quitAll(info string) {
keys := make([]string, 0)
sessions.IterCb(func(uuid string, t interface{}) bool {
sessions.IterCb(func(uuid string, t any) bool {
keys = append(keys, uuid)
desktop := t.(*session)
desktop.escape = true
Expand Down Expand Up @@ -433,7 +433,7 @@ func healthCheck() {
timestamp := now.Unix()
// stores sessions to be disconnected
keys := make([]string, 0)
sessions.IterCb(func(uuid string, t interface{}) bool {
sessions.IterCb(func(uuid string, t any) bool {
desktop := t.(*session)
if timestamp-desktop.lastPack > MaxInterval {
keys = append(keys, uuid)
Expand Down
4 changes: 2 additions & 2 deletions client/service/terminal/terminal_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func InitTerminal(pack modules.Packet) error {
buffer := make([]byte, 512)
n, err := ptySession.Read(buffer)
buffer = buffer[:n]
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]any{
`output`: hex.EncodeToString(buffer),
}}, pack)
termSession.lastPack = common.Unix
Expand Down Expand Up @@ -167,7 +167,7 @@ func healthCheck() {
timestamp := now.Unix()
// stores sessions to be disconnected
queue := make([]string, 0)
terminals.IterCb(func(uuid string, t interface{}) bool {
terminals.IterCb(func(uuid string, t any) bool {
termSession := t.(*terminal)
if timestamp-termSession.lastPack > MaxInterval {
queue = append(queue, uuid)
Expand Down
75 changes: 24 additions & 51 deletions client/service/terminal/terminal_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@ package terminal
import (
"Spark/client/common"
"Spark/modules"
"bytes"
"encoding/hex"
"io"
"os"
"os/exec"
"reflect"
"runtime"
"syscall"
"time"

"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)

type terminal struct {
Expand All @@ -25,7 +20,13 @@ type terminal struct {
stdin *io.WriteCloser
}

var defaultCmd = ``

func init() {
defer func() {
recover()
}()
syscall.NewLazyDLL(`kernel32.dll`).NewProc(`SetConsoleCP`).Call(65001)
go healthCheck()
}

Expand All @@ -34,16 +35,19 @@ func InitTerminal(pack modules.Packet) error {
stdout, err := cmd.StdoutPipe()
if err != nil {
cmd.Process.Kill()
cmd.Process.Release()
return err
}
stderr, err := cmd.StderrPipe()
if err != nil {
cmd.Process.Kill()
cmd.Process.Release()
return err
}
stdin, err := cmd.StdinPipe()
if err != nil {
cmd.Process.Kill()
cmd.Process.Release()
return err
}
termSession := &terminal{
Expand All @@ -62,13 +66,7 @@ func InitTerminal(pack modules.Packet) error {
n, err := rc.Read(buffer)
buffer = buffer[:n]

// clear screen
if len(buffer) == 1 && buffer[0] == 12 {
buffer = []byte{27, 91, 72, 27, 91, 50, 74}
}

buffer, _ = encodeUTF8(buffer)
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]interface{}{
common.WSConn.SendCallback(modules.Packet{Act: `outputTerminal`, Data: map[string]any{
`output`: hex.EncodeToString(buffer),
}}, pack)
termSession.lastPack = common.Unix
Expand Down Expand Up @@ -106,11 +104,6 @@ func InputTerminal(pack modules.Packet) error {
return nil
}
terminal := val.(*terminal)
if len(data) == 1 && data[0] == '\x03' {
terminal.cmd.Process.Signal(os.Interrupt)
return nil
}
data, _ = decodeUTF8(data)
(*terminal.stdin).Write(data)
terminal.lastPack = common.Unix
return nil
Expand Down Expand Up @@ -159,45 +152,25 @@ func doKillTerminal(terminal *terminal) {
(*terminal.stdin).Close()
if terminal.cmd.Process != nil {
terminal.cmd.Process.Kill()
terminal.cmd.Process.Release()
}
}

func getTerminal() string {
return `cmd.exe`
}

func encodeUTF8(s []byte) ([]byte, error) {
if runtime.GOOS == `windows` {
return gbkToUtf8(s)
} else {
return s, nil
var cmdTable = []string{
`powershell.exe`,
`cmd.exe`,
}
}

func decodeUTF8(s []byte) ([]byte, error) {
if runtime.GOOS == `windows` {
return utf8ToGbk(s)
} else {
return s, nil
}
}

func gbkToUtf8(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GB18030.NewDecoder())
d, e := io.ReadAll(reader)
if e != nil {
return nil, e
if defaultCmd != `` {
return defaultCmd
}
return d, nil
}

func utf8ToGbk(s []byte) ([]byte, error) {
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GB18030.NewEncoder())
d, e := io.ReadAll(reader)
if e != nil {
return nil, e
for _, cmd := range cmdTable {
if _, err := exec.LookPath(cmd); err == nil {
defaultCmd = cmd
return cmd
}
}
return d, nil
return `cmd.exe`
}

func healthCheck() {
Expand All @@ -206,7 +179,7 @@ func healthCheck() {
timestamp := now.Unix()
// stores sessions to be disconnected
keys := make([]string, 0)
terminals.IterCb(func(uuid string, t interface{}) bool {
terminals.IterCb(func(uuid string, t any) bool {
termSession := t.(*terminal)
if timestamp-termSession.lastPack > MaxInterval {
keys = append(keys, uuid)
Expand Down
2 changes: 1 addition & 1 deletion server/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func CheckDevice(deviceID, connUUID string) (string, bool) {
}
} else {
tempConnUUID := ``
Devices.IterCb(func(uuid string, v interface{}) bool {
Devices.IterCb(func(uuid string, v any) bool {
device := v.(*modules.Device)
if device.ID == deviceID {
tempConnUUID = uuid
Expand Down
10 changes: 5 additions & 5 deletions server/handler/bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type Bridge struct {
lock *sync.Mutex
Dst *gin.Context
Src *gin.Context
ext interface{}
ext any
OnPull func(bridge *Bridge)
OnPush func(bridge *Bridge)
OnFinish func(bridge *Bridge)
Expand All @@ -36,7 +36,7 @@ func init() {
for now := range time.NewTicker(15 * time.Second).C {
var queue []string
timestamp := now.Unix()
bridges.IterCb(func(k string, v interface{}) bool {
bridges.IterCb(func(k string, v any) bool {
b := v.(*Bridge)
if timestamp-b.creation > 60 && !b.using {
b.lock.Lock()
Expand Down Expand Up @@ -181,7 +181,7 @@ func BridgePull(ctx *gin.Context) {
}
}

func AddBridge(ext interface{}, uuid string) *Bridge {
func AddBridge(ext any, uuid string) *Bridge {
bridge := &Bridge{
creation: common.Unix,
uuid: uuid,
Expand All @@ -193,7 +193,7 @@ func AddBridge(ext interface{}, uuid string) *Bridge {
return bridge
}

func AddBridgeWithSrc(ext interface{}, uuid string, Src *gin.Context) *Bridge {
func AddBridgeWithSrc(ext any, uuid string, Src *gin.Context) *Bridge {
bridge := &Bridge{
creation: common.Unix,
uuid: uuid,
Expand All @@ -206,7 +206,7 @@ func AddBridgeWithSrc(ext interface{}, uuid string, Src *gin.Context) *Bridge {
return bridge
}

func AddBridgeWithDst(ext interface{}, uuid string, Dst *gin.Context) *Bridge {
func AddBridgeWithDst(ext any, uuid string, Dst *gin.Context) *Bridge {
bridge := &Bridge{
creation: common.Unix,
uuid: uuid,
Expand Down
8 changes: 4 additions & 4 deletions server/handler/utility/utility.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Sender func(pack modules.Packet, session *melody.Session) bool

// CheckForm checks if the form contains the required fields.
// Every request must contain connection UUID or device ID.
func CheckForm(ctx *gin.Context, form interface{}) (string, bool) {
func CheckForm(ctx *gin.Context, form any) (string, bool) {
var base struct {
Conn string `json:"uuid" yaml:"uuid" form:"uuid"`
Device string `json:"device" yaml:"device" form:"device"`
Expand Down Expand Up @@ -71,7 +71,7 @@ func OnDevicePack(data []byte, session *melody.Session) error {
// If so, then find the session and let client quit.
// This will keep only one connection remained per device.
exSession := ``
common.Devices.IterCb(func(uuid string, v interface{}) bool {
common.Devices.IterCb(func(uuid string, v any) bool {
device := v.(*modules.Device)
if device.ID == pack.Device.ID {
exSession = uuid
Expand Down Expand Up @@ -173,8 +173,8 @@ func CheckUpdate(ctx *gin.Context) {

// GetDevices will return all info about all clients.
func GetDevices(ctx *gin.Context) {
devices := map[string]interface{}{}
common.Devices.IterCb(func(uuid string, v interface{}) bool {
devices := map[string]any{}
common.Devices.IterCb(func(uuid string, v any) bool {
device := v.(*modules.Device)
devices[uuid] = *device
return true
Expand Down
2 changes: 1 addition & 1 deletion server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ func authCheck() gin.HandlerFunc {
go func() {
for now := range time.NewTicker(60 * time.Second).C {
var queue []string
tokens.IterCb(func(key string, v interface{}) bool {
tokens.IterCb(func(key string, v any) bool {
if now.Unix()-v.(int64) > 1800 {
queue = append(queue, key)
}
Expand Down
10 changes: 0 additions & 10 deletions web/src/components/desktop.css

This file was deleted.

3 changes: 1 addition & 2 deletions web/src/components/desktop.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import DraggableModal from "./modal";
import CryptoJS from "crypto-js";
import {Button, message} from "antd";
import {FullscreenOutlined, ReloadOutlined} from "@ant-design/icons";
import "./desktop.css";

let ws = null;
let ctx = null;
Expand Down Expand Up @@ -74,8 +73,8 @@ function ScreenModal(props) {
clearInterval(ticker);
ticker = setInterval(() => {
setBandwidth(bytes);
bytes = 0;
setFps(frames);
bytes = 0;
frames = 0;
ticks++;
if (ticks > 10 && conn) {
Expand Down
Loading

0 comments on commit f69822b

Please sign in to comment.