From 16b808bb21edddab72a492b8ed062979b3cd7fad Mon Sep 17 00:00:00 2001 From: sawka Date: Wed, 28 Dec 2022 13:56:19 -0800 Subject: [PATCH] working on autoconnect --- cmd/main-server.go | 4 +++- pkg/cmdrunner/resolver.go | 10 ++++++++-- pkg/remote/remote.go | 28 ++++++++++++++++++++++++++-- pkg/scbase/scbase.go | 10 +++++++++- pkg/scws/scws.go | 4 ++-- pkg/sstore/dbops.go | 7 ++----- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/cmd/main-server.go b/cmd/main-server.go index b6c27b0e1..38b622c2e 100644 --- a/cmd/main-server.go +++ b/cmd/main-server.go @@ -35,8 +35,10 @@ const HttpWriteTimeout = 21 * time.Second const HttpMaxHeaderBytes = 60000 const HttpTimeoutDuration = 21 * time.Second -const WebSocketServerAddr = "localhost:8081" const MainServerAddr = "localhost:8080" +const WebSocketServerAddr = "localhost:8081" +const MainServerDevAddr = "localhost:8090" +const WebSocketServerDevAddr = "localhost:8091" const WSStateReconnectTime = 30 * time.Second const WSStatePacketChSize = 20 diff --git a/pkg/cmdrunner/resolver.go b/pkg/cmdrunner/resolver.go index 1fc63b1f8..e70135b28 100644 --- a/pkg/cmdrunner/resolver.go +++ b/pkg/cmdrunner/resolver.go @@ -270,10 +270,16 @@ func resolveUiIds(ctx context.Context, pk *scpacket.FeCommandPacketType, rtype i } if rtype&R_RemoteConnected > 0 { if !rtn.Remote.RState.IsConnected() { - return rtn, fmt.Errorf("remote '%s' is not connected", rtn.Remote.DisplayName) + err = rtn.Remote.MShell.TryAutoConnect() + if err != nil { + return rtn, fmt.Errorf("error trying to auto-connect remote %q", rtn.Remote.DisplayName) + } + } + if !rtn.Remote.RState.IsConnected() { + return rtn, fmt.Errorf("remote %q is not connected", rtn.Remote.DisplayName) } if rtn.Remote.StatePtr == nil || rtn.Remote.FeState == nil { - return rtn, fmt.Errorf("remote '%s' state is not available", rtn.Remote.DisplayName) + return rtn, fmt.Errorf("remote %q state is not available", rtn.Remote.DisplayName) } } return rtn, nil diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index c2eee2fdb..8b30aea7f 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -93,6 +93,7 @@ type MShellProc struct { MakeClientCancelFn context.CancelFunc StateMap map[string]*packet.ShellState // sha1->state CurrentState string // sha1 + NumTryConnect int // install InstallStatus string @@ -247,7 +248,7 @@ func LoadRemoteById(ctx context.Context, remoteId string) error { defer GlobalStore.Lock.Unlock() existingRemote := GlobalStore.Map[remoteId] if existingRemote != nil { - return fmt.Errorf("cannot add remote %d, already in global map", remoteId) + return fmt.Errorf("cannot add remote %s, already in global map", remoteId) } GlobalStore.Map[r.RemoteId] = msh if r.ConnectMode == sstore.ConnectModeStartup { @@ -1234,7 +1235,7 @@ func RunCommand(ctx context.Context, sessionId string, windowId string, remotePt return nil, nil, fmt.Errorf("cannot run command while a stateful command is still running: %v", err) } if line == nil { - return nil, nil, fmt.Errorf("cannot run command while a stateful command is still running %s", *existingPSC, windowId) + return nil, nil, fmt.Errorf("cannot run command while a stateful command is still running %s", *existingPSC) } return nil, nil, fmt.Errorf("cannot run command while a stateful command (linenum=%d) is still running", line.LineNum) } @@ -1821,3 +1822,26 @@ func (msh *MShellProc) getFeStateFromDiff(stateDiff *packet.ShellStateDiff) (*ss return sstore.FeStateFromShellState(&newState), nil } } + +func (msh *MShellProc) TryAutoConnect() error { + if msh.IsConnected() { + return nil + } + rcopy := msh.GetRemoteCopy() + if !rcopy.AutoInstall { + return nil + } + var err error + msh.WithLock(func() { + if msh.NumTryConnect > 5 { + err = fmt.Errorf("cannot auto-connect remote %q (too many unsuccessful tries)", msh.Remote.GetName()) + return + } + msh.NumTryConnect++ + }) + if err != nil { + return err + } + msh.Launch() + return nil +} diff --git a/pkg/scbase/scbase.go b/pkg/scbase/scbase.go index 3bcd8bde4..b70289077 100644 --- a/pkg/scbase/scbase.go +++ b/pkg/scbase/scbase.go @@ -19,9 +19,11 @@ import ( const HomeVarName = "HOME" const PromptHomeVarName = "PROMPT_HOME" +const PromptDevVarName = "PROMPT_DEV" const SessionsDirBaseName = "sessions" const PromptLockFile = "prompt.lock" const PromptDirName = "prompt" +const PromptDevDirName = "prompt-dev" const PromptAppPathVarName = "PROMPT_APP_PATH" const PromptVersion = "v0.1.0" const PromptAuthKeyFileName = "prompt.authkey" @@ -37,7 +39,13 @@ func GetPromptHomeDir() string { if homeVar == "" { homeVar = "/" } - scHome = path.Join(homeVar, PromptDirName) + pdev := os.Getenv(PromptDevVarName) + if pdev != "" { + scHome = path.Join(homeVar, PromptDevDirName) + } else { + scHome = path.Join(homeVar, PromptDirName) + } + } return scHome } diff --git a/pkg/scws/scws.go b/pkg/scws/scws.go index 34a1cd5a8..b84fb4ba6 100644 --- a/pkg/scws/scws.go +++ b/pkg/scws/scws.go @@ -208,7 +208,7 @@ func (ws *WSState) RunWSRead() { err := ws.handleWatchScreen(wsPk) if err != nil { // TODO send errors back to client, likely unrecoverable - log.Printf("[ws %s] error %v\n", err) + log.Printf("[ws %s] error %v\n", ws.ClientId, err) } continue } @@ -264,7 +264,7 @@ func sendCmdInput(pk *scpacket.FeInputPacketType) error { } msh := remote.GetRemoteById(pk.Remote.RemoteId) if msh == nil { - return fmt.Errorf("remote %d not found", pk.Remote.RemoteId) + return fmt.Errorf("remote %s not found", pk.Remote.RemoteId) } if len(pk.InputData64) > 0 { inputLen := packet.B64DecodedLen(pk.InputData64) diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 1f30fb347..5e81c9794 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -886,7 +886,6 @@ func CleanWindows(sessionId string) { } func ArchiveScreen(ctx context.Context, sessionId string, screenId string) (UpdatePacket, error) { - var newActiveScreenId string txErr := WithTx(ctx, func(tx *TxWrap) error { query := `SELECT screenid FROM screen WHERE sessionid = ? AND screenid = ?` if !tx.Exists(query, sessionId, screenId) { @@ -909,7 +908,6 @@ func ArchiveScreen(ctx context.Context, sessionId string, screenId string) (Upda screenIds := tx.SelectStrings(`SELECT screenid FROM screen WHERE sessionid = ? AND NOT archived ORDER BY screenidx`, sessionId) nextId := getNextId(screenIds, screenId) tx.ExecWrap(`UPDATE session SET activescreenid = ? WHERE sessionid = ?`, nextId, sessionId) - newActiveScreenId = nextId } return nil }) @@ -943,7 +941,6 @@ func UnArchiveScreen(ctx context.Context, sessionId string, screenId string) err } func DeleteScreen(ctx context.Context, sessionId string, screenId string) (UpdatePacket, error) { - var newActiveScreenId string txErr := WithTx(ctx, func(tx *TxWrap) error { query := `SELECT screenid FROM screen WHERE sessionid = ? AND screenid = ?` if !tx.Exists(query, sessionId, screenId) { @@ -959,7 +956,6 @@ func DeleteScreen(ctx context.Context, sessionId string, screenId string) (Updat screenIds := tx.SelectStrings(`SELECT screenid FROM screen WHERE sessionid = ? AND NOT archived ORDER BY screenidx`, sessionId) nextId := getNextId(screenIds, screenId) tx.ExecWrap(`UPDATE session SET activescreenid = ? WHERE sessionid = ?`, nextId, sessionId) - newActiveScreenId = nextId } query = `DELETE FROM screen_window WHERE sessionid = ? AND screenid = ?` tx.ExecWrap(query, sessionId, screenId) @@ -976,7 +972,8 @@ func DeleteScreen(ctx context.Context, sessionId string, screenId string) (Updat return nil, err } bareSession.Screens = append(bareSession.Screens, &ScreenType{SessionId: sessionId, ScreenId: screenId, Remove: true}) - return ModelUpdate{Sessions: []*SessionType{bareSession}}, nil + update := ModelUpdate{Sessions: []*SessionType{bareSession}} + return update, nil } func GetRemoteState(ctx context.Context, sessionId string, windowId string, remotePtr RemotePtrType) (*packet.ShellState, *ShellStatePtr, error) {