master
Evan Chen 2021-11-19 17:19:50 +08:00
parent 7aec30d473
commit f309009a76
4 changed files with 113 additions and 69 deletions

View File

@ -3,12 +3,14 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"net"
"net/http" "net/http"
"os" "os"
"strings" "strings"
"kumoly.io/lib/klog" "github.com/rs/zerolog"
"kumoly.io/lib/ksrv" "github.com/rs/zerolog/log"
"kumoly.io/lib/guard"
"kumoly.io/tools/gterm" "kumoly.io/tools/gterm"
) )
@ -27,17 +29,20 @@ var Version = "0.0.0"
var Build = "alpha" var Build = "alpha"
var ( var (
flagAllowIP string flagAllowIPNet string
flagAppName string flagAppName string
flagAddr string flagAddr string
flagShell string flagShell string
flagDir string flagDir string
flagLogLevel int flagLogLevel int
flagDev bool flagLogPretty bool
flagVer bool flagDev bool
flagArgs arrayFlags flagVer bool
flagProfile bool flagArgs arrayFlags
flagSalt string flagProfile bool
flagSalt string
flagUsr string
flagPasswd string
) )
func init() { func init() {
@ -47,11 +52,14 @@ func init() {
flag.StringVar(&flagDir, "dir", "", "the working dir that the shell will start from") flag.StringVar(&flagDir, "dir", "", "the working dir that the shell will start from")
flag.Var(&flagArgs, "arg", "additional args to pass to cmd, multiple args can be passed, ex. -arg a -arg b") flag.Var(&flagArgs, "arg", "additional args to pass to cmd, multiple args can be passed, ex. -arg a -arg b")
flag.BoolVar(&flagDev, "dev", false, "set the system to development mode") flag.BoolVar(&flagDev, "dev", false, "set the system to development mode")
flag.IntVar(&flagLogLevel, "log-level", 9, "log level, error:1 debug:2 warn:4 info:8") flag.IntVar(&flagLogLevel, "log-level", 1, "log level [-1(trace):5(panic)] 7 to disable")
flag.StringVar(&flagAllowIP, "allow", "", "restrict ip") flag.StringVar(&flagAllowIPNet, "allow", "", "restrict ip in a specific ip net")
flag.BoolVar(&flagProfile, "profile", false, "print default profile, could be invoked with <(..)") flag.BoolVar(&flagProfile, "profile", false, "print default profile, could be invoked with <(..)")
flag.StringVar(&flagSalt, "salt", "", "add salt to encoded keyparam") flag.StringVar(&flagSalt, "salt", "", "add salt to encoded keyparam")
flag.BoolVar(&flagVer, "v", false, "show version") flag.BoolVar(&flagVer, "v", false, "show version")
flag.BoolVar(&flagLogPretty, "pretty", false, "log message in human readable format (the original log is json)")
flag.StringVar(&flagUsr, "usr", "", "username, use basic auth for authentication if user and password are set")
flag.StringVar(&flagPasswd, "passwd", "", "password, use basic auth for authentication if user and password are set")
flag.Usage = func() { flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: gterm [options]\n") fmt.Fprintf(os.Stderr, "Usage: gterm [options]\n")
@ -70,8 +78,18 @@ func main() {
return return
} }
klog.LEVEL = klog.Llevel(flagLogLevel) zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
klog.PROD = !flagDev zerolog.SetGlobalLevel(zerolog.Level(flagLogLevel))
if flagLogPretty {
log.Logger = log.Output(zerolog.ConsoleWriter{
Out: os.Stdout,
TimeFormat: "2006/01/02 15:04:05",
})
}
if flagDev {
log.Logger = log.With().Caller().Logger()
}
log.Logger = log.With().Str("mod", "gtrem").Logger()
g := gterm.New() g := gterm.New()
g.AppName = flagAppName g.AppName = flagAppName
@ -80,33 +98,25 @@ func main() {
g.Dir = flagDir g.Dir = flagDir
g.Salt = flagSalt g.Salt = flagSalt
gd := guard.New()
if flagAllowIPNet != "" {
_, ipnet, err := net.ParseCIDR(flagAllowIPNet)
if err != nil {
log.Panic().Err(err).Msg("")
}
gd.AllowIPNet = ipnet
}
if flagUsr != "" && flagPasswd != "" {
gd.SetBasicAuth(flagUsr, flagPasswd)
}
server := &http.Server{ server := &http.Server{
Addr: flagAddr, Addr: flagAddr,
Handler: Middleware(g), Handler: gd.Guard(g),
} }
klog.Info("gterm starting at ", flagAddr) log.Info().Msgf("gterm starting at %s", flagAddr)
err := server.ListenAndServe() err := server.ListenAndServe()
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
func Middleware(next http.Handler) http.Handler {
log := klog.Sub(flagAppName)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Error(err)
}
}()
ip := ksrv.GetIP(r)
if flagAllowIP != "" {
if !ksrv.MatchIPGlob(ip, flagAllowIP) {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("permission denied"))
}
}
next.ServeHTTP(w, r)
log.Debug(ip, " ", r.URL.String())
})
}

4
go.mod
View File

@ -5,7 +5,8 @@ go 1.17
require ( require (
github.com/creack/pty v1.1.17 github.com/creack/pty v1.1.17
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
kumoly.io/lib/klog v0.0.8 github.com/rs/zerolog v1.26.0
kumoly.io/lib/guard v0.1.1
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298
kumoly.io/lib/xorencrypt v0.1.0 kumoly.io/lib/xorencrypt v0.1.0
) )
@ -13,4 +14,5 @@ require (
require ( require (
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
kumoly.io/lib/klog v0.0.8 // indirect
) )

33
go.sum
View File

@ -1,12 +1,45 @@
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
kumoly.io/lib/guard v0.1.0 h1:PvFM0bcWbgfZQv4QfRwDmrK9FAjv9QYwfJY3Ffg6JA0=
kumoly.io/lib/guard v0.1.0/go.mod h1:yWg9RDSI6YXkOPmP6Ad93aMqzlxhgW8LOe/ZRjjYX3U=
kumoly.io/lib/guard v0.1.1 h1:aUcn0qVtX6TqRhp7bWSjIRlbWRWtuK0cjCArILTbAcY=
kumoly.io/lib/guard v0.1.1/go.mod h1:yWg9RDSI6YXkOPmP6Ad93aMqzlxhgW8LOe/ZRjjYX3U=
kumoly.io/lib/klog v0.0.8 h1:6hTfDlZh7KGnPrd2tUrauCKRImSnyyN9DHXpey3Czn8= kumoly.io/lib/klog v0.0.8 h1:6hTfDlZh7KGnPrd2tUrauCKRImSnyyN9DHXpey3Czn8=
kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M= kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M=
kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI= kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI=

View File

@ -13,7 +13,7 @@ import (
"github.com/creack/pty" "github.com/creack/pty"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"kumoly.io/lib/klog" "github.com/rs/zerolog/log"
"kumoly.io/lib/ksrv" "kumoly.io/lib/ksrv"
"kumoly.io/lib/ksrv/engine" "kumoly.io/lib/ksrv/engine"
"kumoly.io/lib/xorencrypt" "kumoly.io/lib/xorencrypt"
@ -75,13 +75,12 @@ func New() *GTerm {
// } // }
go func() { go func() {
//print pool //print pool
log := klog.Sub("gterm")
for { for {
cons := []string{} cons := []string{}
for k := range pool { for k := range pool {
cons = append(cons, k) cons = append(cons, k)
} }
log.Info("current connections: ", cons) log.Info().Interface("connections", cons).Msg("")
time.Sleep(5 * time.Minute) time.Sleep(5 * time.Minute)
} }
}() }()
@ -150,7 +149,7 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
close(pool[id]) close(pool[id])
delete(pool, id) delete(pool, id)
}() }()
l := klog.Sub(id) l := log.With().Str("id", id).Logger()
var cmd *exec.Cmd var cmd *exec.Cmd
@ -159,10 +158,10 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
req := &NewCmdRequest{} req := &NewCmdRequest{}
err := json.Unmarshal([]byte(param), req) err := json.Unmarshal([]byte(param), req)
if err != nil { if err != nil {
l.ErrorF(klog.H{"base": newCmd, "decrypt": param}, err) l.Error().Err(err).Str("base", newCmd).Str("decrypt", param).Msg("cmd decode failed")
cmd = g.defaultCmd() cmd = g.defaultCmd()
} else { } else {
l.Info("starting cmd => ", l.M(fmt.Sprintf("%+v", req), klog.FgHiGreen)) l.Info().Interface("cmd", req).Msg("starting cmd")
cmd = exec.Command(req.Cmd, req.Args...) cmd = exec.Command(req.Cmd, req.Args...)
cmd.Env = append(req.Envs, "TERM=xterm-256color") cmd.Env = append(req.Envs, "TERM=xterm-256color")
cmd.Dir = req.Dir cmd.Dir = req.Dir
@ -178,28 +177,28 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
} }
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
l.Error(err) l.Error().Err(err).Msg("upgrade error")
return return
} }
l.Info("connection established.") l.Info().Msg("connection established.")
tty, err := pty.Start(cmd) tty, err := pty.Start(cmd)
if err != nil { if err != nil {
l.Error(err) l.Error().Err(err).Msg("start tty error")
conn.WriteMessage(websocket.TextMessage, []byte(err.Error())) conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
} }
defer func() { defer func() {
if err := cmd.Process.Kill(); err != nil { if err := cmd.Process.Kill(); err != nil {
l.Error(err) l.Error().Err(err).Msg("proccess kill error")
} }
if _, err := cmd.Process.Wait(); err != nil { if _, err := cmd.Process.Wait(); err != nil {
l.Error(err) l.Error().Err(err).Msg("proccess wait error")
} }
if err := tty.Close(); err != nil { if err := tty.Close(); err != nil {
l.Error(err) l.Error().Err(err).Msg("tty close error")
} }
if err := conn.Close(); err != nil { if err := conn.Close(); err != nil {
l.Error(err) l.Error().Err(err).Msg("conn close error")
} }
}() }()
@ -215,16 +214,16 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
go func() { go func() {
for { for {
if err := conn.WriteMessage(websocket.PingMessage, []byte("keepalive")); err != nil { if err := conn.WriteMessage(websocket.PingMessage, []byte("keepalive")); err != nil {
l.Warn("failed to write ping message") l.Warn().Msg("failed to write ping message")
return return
} }
time.Sleep(g.Timeout / 2) time.Sleep(g.Timeout / 2)
if time.Since(lastPongTime) > g.Timeout { if time.Since(lastPongTime) > g.Timeout {
l.Warn("failed to get response from ping, triggering disconnect now...") l.Warn().Msg("failed to get response from ping, triggering disconnect now...")
waiter <- struct{}{} waiter <- struct{}{}
return return
} }
l.Debug("received response from ping successfully") l.Debug().Msg("received response from ping successfully")
} }
}() }()
@ -242,19 +241,19 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
buffer := make([]byte, g.BufferSize) buffer := make([]byte, g.BufferSize)
readLength, err := tty.Read(buffer) readLength, err := tty.Read(buffer)
if err != nil { if err != nil {
l.Warn("failed to read from tty: ", err) l.Warn().Err(err).Msg("failed to read from tty")
if err := conn.WriteMessage(websocket.TextMessage, []byte("bye!")); err != nil { if err := conn.WriteMessage(websocket.TextMessage, []byte("bye!")); err != nil {
l.Warn("failed to send termination message from tty to xterm.js: ", err) l.Warn().Err(err).Msg("failed to send termination message from tty to xterm.js")
} }
waiter <- struct{}{} waiter <- struct{}{}
return return
} }
if err := conn.WriteMessage(websocket.BinaryMessage, buffer[:readLength]); err != nil { if err := conn.WriteMessage(websocket.BinaryMessage, buffer[:readLength]); err != nil {
l.Warn("failed to send ", readLength, " bytes from tty to xterm.js") l.Warn().Msgf("failed to send %s bytes from tty to xterm.js", readLength)
errorCounter++ errorCounter++
continue continue
} }
l.Debug("sent message of size ", readLength, " bytes from tty to xterm.js") l.Debug().Msgf("sent message of size %s bytes from tty to xterm.js", readLength)
errorCounter = 0 errorCounter = 0
} }
}() }()
@ -266,7 +265,7 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
messageType, data, err := conn.ReadMessage() messageType, data, err := conn.ReadMessage()
if err != nil { if err != nil {
if !connectionClosed { if !connectionClosed {
l.Warn("failed to get next reader: ", err) l.Warn().Err(err).Msg("failed to get next reader")
} }
return return
} }
@ -276,11 +275,11 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
if !ok { if !ok {
dataType = "uunknown" dataType = "uunknown"
} }
l.Debug(fmt.Sprintf("received %s (type: %v) message of size %v byte(s) from xterm.js with key sequence: %v", dataType, messageType, dataLength, dataBuffer)) l.Debug().Msgf("received %s (type: %v) message of size %v byte(s) from xterm.js with key sequence: %v", dataType, messageType, dataLength, dataBuffer)
// process // process
if dataLength == -1 { // invalid if dataLength == -1 { // invalid
l.Warn("failed to get the correct number of bytes read, ignoring message") l.Warn().Msg("failed to get the correct number of bytes read, ignoring message")
continue continue
} }
@ -290,15 +289,15 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
ttySize := &TTYSize{} ttySize := &TTYSize{}
resizeMessage := bytes.Trim(dataBuffer[1:], " \n\r\t\x00\x01") resizeMessage := bytes.Trim(dataBuffer[1:], " \n\r\t\x00\x01")
if err := json.Unmarshal(resizeMessage, ttySize); err != nil { if err := json.Unmarshal(resizeMessage, ttySize); err != nil {
l.Warn(fmt.Sprintf("failed to unmarshal received resize message '%s': %s", string(resizeMessage), err)) l.Warn().Err(err).Msgf("failed to unmarshal received resize message '%s'", string(resizeMessage))
continue continue
} }
l.DebugF(klog.H{"rows": ttySize.Rows, "columns": ttySize.Cols}, "resizing tty...") l.Debug().Int("rows", int(ttySize.Rows)).Int("columns", int(ttySize.Cols)).Msg("resizing tty...")
if err := pty.Setsize(tty, &pty.Winsize{ if err := pty.Setsize(tty, &pty.Winsize{
Rows: ttySize.Rows, Rows: ttySize.Rows,
Cols: ttySize.Cols, Cols: ttySize.Cols,
}); err != nil { }); err != nil {
l.Warn("failed to resize tty, error: ", err) l.Warn().Err(err).Msg("failed to resize tty")
} }
continue continue
} }
@ -307,16 +306,16 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
// write to tty // write to tty
bytesWritten, err := tty.Write(dataBuffer) bytesWritten, err := tty.Write(dataBuffer)
if err != nil { if err != nil {
l.Warn(fmt.Sprintf("failed to write %v bytes to tty: %s", len(dataBuffer), err)) l.Warn().Err(err).Msgf("failed to write %v bytes to tty", len(dataBuffer))
continue continue
} }
l.Debug(bytesWritten, " bytes written to tty...") l.Debug().Msgf("%d bytes written to tty...", bytesWritten)
} }
}() }()
<-waiter <-waiter
close(waiter) close(waiter)
l.Info("closing connection...") l.Info().Msg("closing connection...")
connectionClosed = true connectionClosed = true
} }