From d251cbdd883c3c2e33155a67d552eb2e671a6c83 Mon Sep 17 00:00:00 2001 From: sawka Date: Sun, 25 Sep 2022 00:26:33 -0700 Subject: [PATCH] save/restore winsize w/ clientdata --- cmd/main-server.go | 48 ++++++++++++++++++++++++++++++-- db/migrations/000001_init.up.sql | 3 +- pkg/sstore/dbops.go | 9 ++++++ pkg/sstore/sstore.go | 34 ++++++++++++++-------- 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/cmd/main-server.go b/cmd/main-server.go index fd89e92b..14e7d4c6 100644 --- a/cmd/main-server.go +++ b/cmd/main-server.go @@ -116,6 +116,46 @@ func writeToFifo(fifoName string, data []byte) error { return nil } +func HandleGetClientData(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Vary", "Origin") + w.Header().Set("Cache-Control", "no-cache") + cdata, err := sstore.EnsureClientData(r.Context()) + if err != nil { + WriteJsonError(w, err) + return + } + WriteJsonSuccess(w, cdata) + return +} + +func HandleSetWinSize(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS") + w.Header().Set("Vary", "Origin") + w.Header().Set("Cache-Control", "no-cache") + if r.Method == "GET" || r.Method == "OPTIONS" { + w.WriteHeader(200) + return + } + decoder := json.NewDecoder(r.Body) + var winSize sstore.ClientWinSizeType + err := decoder.Decode(&winSize) + if err != nil { + WriteJsonError(w, fmt.Errorf("error decoding json: %w", err)) + return + } + err = sstore.SetWinSize(r.Context(), winSize) + if err != nil { + WriteJsonError(w, fmt.Errorf("error setting winsize: %w", err)) + return + } + WriteJsonSuccess(w, true) + return +} + // params: sessionid, windowid func HandleGetWindow(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) @@ -322,12 +362,12 @@ func main() { fmt.Printf("[error] migrate up: %v\n", err) return } - userData, err := sstore.EnsureClientData(context.Background()) + clientData, err := sstore.EnsureClientData(context.Background()) if err != nil { - fmt.Printf("[error] ensuring user data: %v\n", err) + fmt.Printf("[error] ensuring client data: %v\n", err) return } - fmt.Printf("userid = %s\n", userData.UserId) + fmt.Printf("userid = %s\n", clientData.UserId) err = sstore.EnsureLocalRemote(context.Background()) if err != nil { fmt.Printf("[error] ensuring local remote: %v\n", err) @@ -365,6 +405,8 @@ func main() { gr.HandleFunc("/api/remote-pty", HandleRemotePty) gr.HandleFunc("/api/get-window", HandleGetWindow) gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS") + gr.HandleFunc("/api/get-client-data", HandleGetClientData) + gr.HandleFunc("/api/set-winsize", HandleSetWinSize) server := &http.Server{ Addr: MainServerAddr, ReadTimeout: HttpReadTimeout, diff --git a/db/migrations/000001_init.up.sql b/db/migrations/000001_init.up.sql index 7630007d..40c75e55 100644 --- a/db/migrations/000001_init.up.sql +++ b/db/migrations/000001_init.up.sql @@ -3,7 +3,8 @@ CREATE TABLE client ( userid varchar(36) NOT NULL, activesessionid varchar(36) NOT NULL, userpublickeybytes blob NOT NULL, - userprivatekeybytes blob NOT NULL + userprivatekeybytes blob NOT NULL, + winsize json NOT NULL ); CREATE TABLE session ( diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 55762a3f..10761cab 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -419,6 +419,15 @@ func SetActiveSessionId(ctx context.Context, sessionId string) error { return txErr } +func SetWinSize(ctx context.Context, winSize ClientWinSizeType) error { + txErr := WithTx(ctx, func(tx *TxWrap) error { + query := `UPDATE client SET winsize = ?` + tx.ExecWrap(query, quickJson(winSize)) + return nil + }) + return txErr +} + func containsStr(strs []string, testStr string) bool { for _, s := range strs { if s == testStr { diff --git a/pkg/sstore/sstore.go b/pkg/sstore/sstore.go index e6d39f68..40dcfecc 100644 --- a/pkg/sstore/sstore.go +++ b/pkg/sstore/sstore.go @@ -91,14 +91,23 @@ func GetDB(ctx context.Context) (*sqlx.DB, error) { return globalDB, globalDBErr } +type ClientWinSizeType struct { + Width int `json:"width"` + Height int `json:"height"` + Top int `json:"top"` + Left int `json:"left"` + FullScreen bool `json:"fullscreen,omitempty"` +} + type ClientData struct { - ClientId string `json:"clientid"` - UserId string `json:"userid"` - UserPrivateKeyBytes []byte `json:"-"` - UserPublicKeyBytes []byte `json:"-"` - UserPrivateKey *ecdsa.PrivateKey - UserPublicKey *ecdsa.PublicKey - ActiveSessionId string `json:"activesessionid"` + ClientId string `json:"clientid"` + UserId string `json:"userid"` + UserPrivateKeyBytes []byte `json:"-"` + UserPublicKeyBytes []byte `json:"-"` + UserPrivateKey *ecdsa.PrivateKey `json:"-"` + UserPublicKey *ecdsa.PublicKey `json:"-"` + ActiveSessionId string `json:"activesessionid"` + WinSize ClientWinSizeType `json:"winsize"` } func (c *ClientData) ToMap() map[string]interface{} { @@ -108,6 +117,7 @@ func (c *ClientData) ToMap() map[string]interface{} { rtn["userprivatekeybytes"] = c.UserPrivateKeyBytes rtn["userpublickeybytes"] = c.UserPublicKeyBytes rtn["activesessionid"] = c.ActiveSessionId + rtn["winsize"] = quickJson(c.WinSize) return rtn } @@ -121,6 +131,7 @@ func ClientDataFromMap(m map[string]interface{}) *ClientData { quickSetBytes(&c.UserPrivateKeyBytes, m, "userprivatekeybytes") quickSetBytes(&c.UserPublicKeyBytes, m, "userpublickeybytes") quickSetStr(&c.ActiveSessionId, m, "activesessionid") + quickSetJson(&c.WinSize, m, "winsize") return &c } @@ -792,9 +803,10 @@ func createClientData(tx *TxWrap) error { UserPrivateKeyBytes: pkBytes, UserPublicKeyBytes: pubBytes, ActiveSessionId: "", + WinSize: ClientWinSizeType{}, } - query := `INSERT INTO client ( clientid, userid, activesessionid, userpublickeybytes, userprivatekeybytes) - VALUES (:clientid,:userid,:activesessionid,:userpublickeybytes,:userprivatekeybytes)` + query := `INSERT INTO client ( clientid, userid, activesessionid, userpublickeybytes, userprivatekeybytes, winsize) + VALUES (:clientid,:userid,:activesessionid,:userpublickeybytes,:userprivatekeybytes,:winsize)` tx.NamedExecWrap(query, c.ToMap()) fmt.Printf("create new clientid[%s] userid[%s] with public/private keypair\n", c.ClientId, c.UserId) return nil @@ -814,10 +826,10 @@ func EnsureClientData(ctx context.Context) (*ClientData, error) { return createErr } } - m := tx.GetMap("SELECT * FROM client") + m := tx.GetMap(`SELECT * FROM client`) cdata := ClientDataFromMap(m) if cdata == nil { - return fmt.Errorf("invalid client data") + return fmt.Errorf("no client data found") } rtn = *cdata return nil