Update the server side when the client window changes

pull/25/head
Vasile Popescu 4 years ago committed by Elis Popescu
parent 366edcd23e
commit e8c6caac80

@ -125,6 +125,8 @@ func (c *ttyShareClient) Run() (err error) {
defer term.RestoreTerminal(os.Stdin.Fd(), state) defer term.RestoreTerminal(os.Stdin.Fd(), state)
clearScreen() clearScreen()
protoWS := server.NewTTYProtocolWS(c.wsConn)
monitorWinChanges := func() { monitorWinChanges := func() {
// start monitoring the size of the terminal // start monitoring the size of the terminal
signal.Notify(c.wcChan, syscall.SIGWINCH) signal.Notify(c.wcChan, syscall.SIGWINCH)
@ -132,15 +134,13 @@ func (c *ttyShareClient) Run() (err error) {
for { for {
select { select {
case <-c.wcChan: case <-c.wcChan:
log.Debugf("Detected new win size")
c.updateThisWinSize() c.updateThisWinSize()
c.updateAndDecideStdoutMuted() c.updateAndDecideStdoutMuted()
protoWS.SetWinSize(int(c.winSizes.thisW), int(c.winSizes.thisH))
} }
} }
} }
protoWS := server.NewTTYProtocolWS(c.wsConn)
readLoop := func() { readLoop := func() {
var err error var err error

@ -16,11 +16,11 @@ import (
var version string = "0.0.0" var version string = "0.0.0"
func createServer(frontListenAddress string, frontendPath string, tty io.Writer, sessionID string) *server.TTYServer { func createServer(frontListenAddress string, frontendPath string, pty server.PTYHandler, sessionID string) *server.TTYServer {
config := ttyServer.TTYServerConfig{ config := ttyServer.TTYServerConfig{
FrontListenAddress: frontListenAddress, FrontListenAddress: frontListenAddress,
FrontendPath: frontendPath, FrontendPath: frontendPath,
TTYWriter: tty, PTY: pty,
SessionID: sessionID, SessionID: sessionID,
} }
@ -28,13 +28,16 @@ func createServer(frontListenAddress string, frontendPath string, tty io.Writer,
return server return server
} }
type nilWriter struct { type nilPTY struct {
} }
func (nw *nilWriter) Write(data []byte) (int, error) { func (nw *nilPTY) Write(data []byte) (int, error) {
return len(data), nil return len(data), nil
} }
func (nw *nilPTY) Refresh() {
}
func main() { func main() {
usageString := ` usageString := `
Usage: Usage:
@ -145,12 +148,12 @@ Flags:
ptyMaster := ptyMasterNew() ptyMaster := ptyMasterNew()
ptyMaster.Start(*commandName, strings.Fields(*commandArgs)) ptyMaster.Start(*commandName, strings.Fields(*commandArgs))
var writer io.Writer = ptyMaster var pty server.PTYHandler = ptyMaster
if *readOnly { if *readOnly {
writer = &nilWriter{} pty = &nilPTY{}
} }
server := createServer(*listenAddress, *frontendPath, writer, sessionID) server := createServer(*listenAddress, *frontendPath, pty, sessionID)
if cols, rows, e := ptyMaster.GetWinSize(); e == nil { if cols, rows, e := ptyMaster.GetWinSize(); e == nil {
server.WindowSize(cols, rows) server.WindowSize(cols, rows)
} }
@ -163,9 +166,7 @@ Flags:
mw := io.MultiWriter(os.Stdout, server) mw := io.MultiWriter(os.Stdout, server)
go func() { go func() {
err := server.Run(func(clientAddr string) { err := server.Run()
ptyMaster.Refresh()
})
if err != nil { if err != nil {
log.Debugf("Server done: %s", err.Error()) log.Debugf("Server done: %s", err.Error())
} }

@ -3,9 +3,7 @@ package server
import ( import (
"fmt" "fmt"
"html/template" "html/template"
"io"
"mime" "mime"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -20,7 +18,10 @@ const (
errorNotAllowed = iota errorNotAllowed = iota
) )
type NewClientConnectedCB func(string) type PTYHandler interface {
Write(data []byte) (int, error)
Refresh()
}
// SessionTemplateModel used for templating // SessionTemplateModel used for templating
type AASessionTemplateModel struct { type AASessionTemplateModel struct {
@ -33,16 +34,15 @@ type AASessionTemplateModel struct {
type TTYServerConfig struct { type TTYServerConfig struct {
FrontListenAddress string FrontListenAddress string
FrontendPath string FrontendPath string
TTYWriter io.Writer PTY PTYHandler
SessionID string SessionID string
} }
// TTYServer represents the instance of a tty server // TTYServer represents the instance of a tty server
type TTYServer struct { type TTYServer struct {
httpServer *http.Server httpServer *http.Server
newClientCB NewClientConnectedCB config TTYServerConfig
config TTYServerConfig session *ttyShareSession
session *ttyShareSession
} }
func (server *TTYServer) serveContent(w http.ResponseWriter, r *http.Request, name string) { func (server *TTYServer) serveContent(w http.ResponseWriter, r *http.Request, name string) {
@ -95,12 +95,12 @@ func NewTTYServer(config TTYServerConfig) (server *TTYServer) {
}))) })))
routesHandler.HandleFunc(fmt.Sprintf("/s/%s/", session), func(w http.ResponseWriter, r *http.Request) { routesHandler.HandleFunc(fmt.Sprintf("/s/%s/", session), func(w http.ResponseWriter, r *http.Request) {
wsPath := "/s/" + session + "/ws" wsPath := "/s/" + session + "/ws"
pathPrefix := "/s/" + session pathPrefix := "/s/" + session
// Check the frontend/templates/tty-share.in.html file to see where the template applies // Check the frontend/templates/tty-share.in.html file to see where the template applies
templateModel := struct { templateModel := struct {
PathPrefix string PathPrefix string
WSPath string WSPath string
}{pathPrefix, wsPath} }{pathPrefix, wsPath}
// TODO Extract these in constants // TODO Extract these in constants
@ -113,7 +113,7 @@ func NewTTYServer(config TTYServerConfig) (server *TTYServer) {
server.handleWebsocket(w, r) server.handleWebsocket(w, r)
}) })
routesHandler.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { routesHandler.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
templateModel := struct{PathPrefix string }{session} templateModel := struct{ PathPrefix string }{session}
server.handleWithTemplateHtml(w, r, "404.in.html", templateModel) server.handleWithTemplateHtml(w, r, "404.in.html", templateModel)
}) })
} }
@ -124,7 +124,7 @@ func NewTTYServer(config TTYServerConfig) (server *TTYServer) {
installHandlers(config.SessionID) installHandlers(config.SessionID)
server.httpServer.Handler = routesHandler server.httpServer.Handler = routesHandler
server.session = newTTYShareSession(config.TTYWriter) server.session = newTTYShareSession(config.PTY)
return server return server
} }
@ -146,7 +146,8 @@ func (server *TTYServer) handleWebsocket(w http.ResponseWriter, r *http.Request)
return return
} }
server.newClientCB(conn.RemoteAddr().String()) // On a new connection, ask for a refresh/redraw of the terminal app
server.config.PTY.Refresh()
server.session.HandleWSConnection(conn) server.session.HandleWSConnection(conn)
} }
@ -174,8 +175,7 @@ func (server *TTYServer) handleWithTemplateHtml(responseWriter http.ResponseWrit
} }
func (server *TTYServer) Run(cb NewClientConnectedCB) (err error) { func (server *TTYServer) Run() (err error) {
server.newClientCB = cb
err = server.httpServer.ListenAndServe() err = server.httpServer.ListenAndServe()
log.Debug("Server finished") log.Debug("Server finished")
return return

@ -14,7 +14,7 @@ type ttyShareSession struct {
ttyProtoConnections *list.List ttyProtoConnections *list.List
isAlive bool isAlive bool
lastWindowSizeMsg MsgTTYWinSize lastWindowSizeMsg MsgTTYWinSize
ttyWriter io.Writer ptyHandler PTYHandler
} }
// quick and dirty locked writer // quick and dirty locked writer
@ -37,11 +37,11 @@ func copyList(l *list.List) *list.List {
return newList return newList
} }
func newTTYShareSession(ttyWriter io.Writer) *ttyShareSession { func newTTYShareSession(ptyHandler PTYHandler) *ttyShareSession {
ttyShareSession := &ttyShareSession{ ttyShareSession := &ttyShareSession{
ttyProtoConnections: list.New(), ttyProtoConnections: list.New(),
ttyWriter: ttyWriter, ptyHandler: ptyHandler,
} }
return ttyShareSession return ttyShareSession
@ -104,10 +104,10 @@ func (session *ttyShareSession) HandleWSConnection(wsConn *websocket.Conn) {
for { for {
err := protoConn.ReadAndHandle( err := protoConn.ReadAndHandle(
func(data []byte) { func(data []byte) {
session.ttyWriter.Write(data) session.ptyHandler.Write(data)
}, },
func(cols, rows int) { func(cols, rows int) {
// Maybe ask the server side to refresh/repaint the tty window? session.ptyHandler.Refresh()
}, },
) )

Loading…
Cancel
Save