working on multiple sessions/windows

This commit is contained in:
sawka
2022-07-08 13:23:45 -07:00
parent 368c16eb60
commit ec6c1f5a9a
4 changed files with 192 additions and 35 deletions
+75 -9
View File
@@ -270,19 +270,19 @@ func sendCmdInput(pk *packet.InputPacketType) error {
return msh.SendInput(pk)
}
// params: name
// params: sessionid
func HandleGetSession(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")
qvals := r.URL.Query()
name := qvals.Get("name")
if name == "" {
WriteJsonError(w, fmt.Errorf("must specify a name"))
sessionId := qvals.Get("sessionid")
if sessionId == "" {
WriteJsonError(w, fmt.Errorf("must specify a sessionid"))
return
}
session, err := sstore.GetSessionByName(r.Context(), name)
session, err := sstore.GetSessionById(r.Context(), sessionId)
if err != nil {
WriteJsonError(w, err)
return
@@ -291,6 +291,69 @@ func HandleGetSession(w http.ResponseWriter, r *http.Request) {
return
}
func HandleGetAllSessions(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")
list, err := sstore.GetAllSessions(r.Context())
if err != nil {
WriteJsonError(w, fmt.Errorf("cannot get all sessions: %w", err))
return
}
WriteJsonSuccess(w, list)
return
}
// params: name
func HandleCreateSession(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")
qvals := r.URL.Query()
name := qvals.Get("name")
sessionId, err := sstore.InsertSessionWithName(r.Context(), name)
if err != nil {
WriteJsonError(w, fmt.Errorf("inserting session: %w", err))
return
}
session, err := sstore.GetSessionById(r.Context(), sessionId)
if err != nil {
WriteJsonError(w, fmt.Errorf("getting new session: %w", err))
return
}
WriteJsonSuccess(w, session)
return
}
// params: sessionid, name
func HandleCreateWindow(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")
qvals := r.URL.Query()
sessionId := qvals.Get("sessionid")
if _, err := uuid.Parse(sessionId); err != nil {
WriteJsonError(w, fmt.Errorf("invalid sessionid: %w", err))
return
}
name := qvals.Get("name")
windowId, err := sstore.InsertWindow(r.Context(), sessionId, name)
if err != nil {
WriteJsonError(w, fmt.Errorf("inserting new window: %w", err))
return
}
window, err := sstore.GetWindowById(r.Context(), sessionId, windowId)
if err != nil {
WriteJsonError(w, fmt.Errorf("getting new window: %w", err))
return
}
WriteJsonSuccess(w, window)
return
}
// params: [none]
func HandleGetRemotes(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
@@ -303,7 +366,7 @@ func HandleGetRemotes(w http.ResponseWriter, r *http.Request) {
}
// params: sessionid, windowid
func HandleGetWindowLines(w http.ResponseWriter, r *http.Request) {
func HandleGetWindow(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")
@@ -319,12 +382,12 @@ func HandleGetWindowLines(w http.ResponseWriter, r *http.Request) {
WriteJsonError(w, fmt.Errorf("invalid windowid: %w", err))
return
}
lines, err := sstore.GetWindowLines(r.Context(), sessionId, windowId)
window, err := sstore.GetWindowById(r.Context(), sessionId, windowId)
if err != nil {
WriteJsonError(w, err)
return
}
WriteJsonSuccess(w, lines)
WriteJsonSuccess(w, window)
return
}
@@ -623,9 +686,12 @@ func main() {
go runWebSocketServer()
gr := mux.NewRouter()
gr.HandleFunc("/api/ptyout", HandleGetPtyOut)
gr.HandleFunc("/api/get-all-sessions", HandleGetAllSessions)
gr.HandleFunc("/api/create-session", HandleCreateSession)
gr.HandleFunc("/api/get-session", HandleGetSession)
gr.HandleFunc("/api/get-window-lines", HandleGetWindowLines)
gr.HandleFunc("/api/get-window", HandleGetWindow)
gr.HandleFunc("/api/get-remotes", HandleGetRemotes)
gr.HandleFunc("/api/create-window", HandleCreateWindow)
gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS")
server := &http.Server{
Addr: MainServerAddr,
+115 -25
View File
@@ -84,6 +84,20 @@ func InsertRemote(ctx context.Context, remote *RemoteType) error {
return nil
}
func GetAllSessions(ctx context.Context) ([]*SessionType, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var rtn []*SessionType
query := `SELECT * FROM session`
err = db.SelectContext(ctx, &rtn, query)
if err != nil {
return nil, err
}
return rtn, nil
}
func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
var rtnSession *SessionType
err := WithTx(ctx, func(tx *TxWrap) error {
@@ -128,35 +142,56 @@ func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
return GetSessionById(ctx, sessionId)
}
func GetWindowLines(ctx context.Context, sessionId string, windowId string) ([]*LineType, error) {
var lines []*LineType
db, err := GetDB()
if err != nil {
return nil, err
}
query := `SELECT * FROM line WHERE sessionid = ? AND windowid = ?`
err = db.SelectContext(ctx, &lines, query, sessionId, windowId)
if err != nil {
return nil, err
}
return lines, nil
func GetWindowById(ctx context.Context, sessionId string, windowId string) (*WindowType, error) {
var rtnWindow *WindowType
txErr := WithTx(ctx, func(tx *TxWrap) error {
var window WindowType
query := `SELECT * FROM window WHERE sessionid = ? AND windowid = ?`
found := tx.GetWrap(&window, query, sessionId, windowId)
if !found {
return nil
}
rtnWindow = &window
query = `SELECT * FROM line WHERE sessionid = ? AND windowid = ?`
tx.SelectWrap(&window.Lines, query, sessionId, windowId)
return nil
})
return rtnWindow, txErr
}
// also creates window
func InsertSessionWithName(ctx context.Context, sessionName string) error {
if sessionName == "" {
return fmt.Errorf("invalid session name '%s'", sessionName)
}
session := &SessionType{
SessionId: uuid.New().String(),
Name: sessionName,
}
return WithTx(ctx, func(tx *TxWrap) error {
// also creates default window, returns sessionId
// if sessionName == "", it will be generated
func InsertSessionWithName(ctx context.Context, sessionName string) (string, error) {
newSessionId := uuid.New().String()
txErr := WithTx(ctx, func(tx *TxWrap) error {
if sessionName == "" {
var names []string
query := `SELECT name FROM session`
tx.GetWrap(&names, query)
snum := len(names) + 1
for {
sessionName = fmt.Sprintf("session-%d", snum)
if !containsStr(names, sessionName) {
break
}
snum++
}
} else {
var dupSessionId string
query := `SELECT sessionid FROM session WHERE name = ?`
tx.GetWrap(&dupSessionId, query, sessionName)
if dupSessionId != "" {
return fmt.Errorf("cannot create session with duplicate name")
}
}
newSession := &SessionType{
SessionId: newSessionId,
Name: sessionName,
}
query := `INSERT INTO session (sessionid, name) VALUES (:sessionid, :name)`
tx.NamedExecWrap(query, session)
tx.NamedExecWrap(query, newSession)
window := &WindowType{
SessionId: session.SessionId,
SessionId: newSessionId,
WindowId: uuid.New().String(),
Name: DefaultWindowName,
CurRemote: LocalRemoteName,
@@ -165,6 +200,61 @@ func InsertSessionWithName(ctx context.Context, sessionName string) error {
tx.NamedExecWrap(query, window)
return nil
})
return newSessionId, txErr
}
func containsStr(strs []string, testStr string) bool {
for _, s := range strs {
if s == testStr {
return true
}
}
return false
}
// if windowName == "", it will be generated
// returns (windowid, err)
func InsertWindow(ctx context.Context, sessionId string, windowName string) (string, error) {
var newWindowId string
txErr := WithTx(ctx, func(tx *TxWrap) error {
var testSessionId string
query := `SELECT sesssionid FROM session WHERE sessionid = ?`
sessionExists := tx.GetWrap(&testSessionId, query, sessionId)
if !sessionExists {
return fmt.Errorf("cannot insert window, session does not exist")
}
if windowName == "" {
var names []string
query = `SELECT name FROM window WHERE sessionid = ?`
tx.GetWrap(&names, query, sessionId)
wnum := len(names) + 1
for {
windowName = fmt.Sprintf("w%d", wnum)
if !containsStr(names, windowName) {
break
}
wnum++
}
} else {
var testWindowId string
query = `SELECT windowid FROM window WHERE sessionid = ? AND name = ?`
windowExists := tx.GetWrap(&testWindowId, query, sessionId, windowName)
if windowExists {
return fmt.Errorf("cannot insert window, name already exists in session")
}
}
newWindowId = uuid.New().String()
window := &WindowType{
SessionId: sessionId,
WindowId: newWindowId,
Name: windowName,
CurRemote: LocalRemoteName,
}
query = `INSERT INTO window (sessionid, windowid, name, curremote, version) VALUES (:sessionid, :windowid, :name, :curremote, :version)`
tx.NamedExecWrap(query, window)
return nil
})
return newWindowId, txErr
}
func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
+1
View File
@@ -16,6 +16,7 @@ func AppendToCmdPtyBlob(ctx context.Context, sessionId string, cmdId string, dat
if err != nil {
return err
}
defer fd.Close()
if len(data) == 0 {
return nil
}
+1 -1
View File
@@ -327,7 +327,7 @@ func EnsureDefaultSession(ctx context.Context) (*SessionType, error) {
if session != nil {
return session, nil
}
err = InsertSessionWithName(ctx, DefaultSessionName)
_, err = InsertSessionWithName(ctx, DefaultSessionName)
if err != nil {
return nil, err
}