diff --git a/internal/server/telnet.go b/internal/server/telnet.go index dbf7296a..6956352c 100644 --- a/internal/server/telnet.go +++ b/internal/server/telnet.go @@ -13,6 +13,7 @@ import ( "github.com/gabe565/ascii-movie/internal/server/idleconn" "github.com/gabe565/ascii-movie/internal/server/telnet" "github.com/gabe565/ascii-movie/internal/util" + "github.com/muesli/termenv" flag "github.com/spf13/pflag" ) @@ -112,13 +113,20 @@ func (s *TelnetServer) Handler(ctx context.Context, conn net.Conn, m *movie.Movi ctx, cancel := context.WithCancel(ctx) defer cancel() - termCh := make(chan string) + termCh := make(chan telnet.TermInfo) go func() { // Proxy input to program _ = telnet.Proxy(conn, inW, termCh) cancel() }() - profile := util.Profile(<-termCh) + + var profile termenv.Profile + select { + case info := <-termCh: + profile = util.Profile(info.Term) + case <-time.After(250 * time.Millisecond): + profile = termenv.ANSI256 + } player := movie.NewPlayer(m, logger, profile) program := tea.NewProgram( @@ -129,8 +137,20 @@ func (s *TelnetServer) Handler(ctx context.Context, conn net.Conn, m *movie.Movi ) go func() { - <-ctx.Done() - program.Send(movie.Quit()) + for { + select { + case info := <-termCh: + if info.Width != 0 && info.Height != 0 { + program.Send(tea.WindowSizeMsg{ + Width: int(info.Width), + Height: int(info.Height), + }) + } + case <-ctx.Done(): + program.Send(movie.Quit()) + return + } + } }() go func() { diff --git a/internal/server/telnet/proxy.go b/internal/server/telnet/proxy.go index 1dc466a3..7b9b7545 100644 --- a/internal/server/telnet/proxy.go +++ b/internal/server/telnet/proxy.go @@ -2,6 +2,8 @@ package telnet import ( "bufio" + "bytes" + "encoding/binary" "errors" "io" "net" @@ -11,8 +13,18 @@ import ( log "github.com/sirupsen/logrus" ) -func Proxy(conn net.Conn, proxy io.Writer, termCh chan string) error { +type TermInfo struct { + Term string + WindowSize +} + +type WindowSize struct { + Width, Height uint16 +} + +func Proxy(conn net.Conn, proxy io.Writer, termCh chan TermInfo) error { reader := bufio.NewReaderSize(conn, 64) + var info TermInfo var wroteTelnetCommands bool var wroteTermType bool @@ -23,15 +35,6 @@ func Proxy(conn net.Conn, proxy io.Writer, termCh chan string) error { return err } - go func() { - time.Sleep(250 * time.Millisecond) - if !wroteTermType { - wroteTermType = true - log.Trace("Did not get terminal type in time") - close(termCh) - } - }() - for { b, err := reader.ReadByte() if err != nil { @@ -48,6 +51,7 @@ func Proxy(conn net.Conn, proxy io.Writer, termCh chan string) error { Iac, Will, Echo, Iac, Will, SuppressGoAhead, Iac, Do, TerminalType, + Iac, Do, NegotiateAboutWindowSize, ); err != nil { log.WithError(err).Error("Failed to write Telnet commands") } @@ -77,10 +81,18 @@ func Proxy(conn net.Conn, proxy io.Writer, termCh chan string) error { case TerminalType: if len(command) > 5 && !wroteTermType { wroteTermType = true - term := string(command[2 : len(command)-2]) + info.Term = string(command[2 : len(command)-2]) log.Trace("Got terminal type") - termCh <- term - close(termCh) + termCh <- info + } + case NegotiateAboutWindowSize: + if len(command) > 5 { + log.Trace("Got window size") + r := bytes.NewReader(command[1 : len(command)-2]) + if err := binary.Read(r, binary.BigEndian, &info.WindowSize); err != nil { + return err + } + termCh <- info } } }