From 7a4d66bcf860549b8f73fbc5c72a4eaed2fbe61a Mon Sep 17 00:00:00 2001 From: Nick Dumas Date: Sat, 24 Jan 2026 19:24:13 -0500 Subject: [PATCH] working telnet echo server --- core/core.go | 9 +++++++-- core/server.go | 48 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/core/core.go b/core/core.go index 0f5908d..35599d7 100644 --- a/core/core.go +++ b/core/core.go @@ -66,7 +66,12 @@ func (a *App) Run(ctx context.Context) { s := NewServer(ctx, a.L, a.Config.Port) go s.Start() - for session := range s.Sessions { - go session.Start() + for { + select { + case <-ctx.Done(): + return + case session := <-s.Sessions: + go session.Start() + } } } diff --git a/core/server.go b/core/server.go index 4fdc535..71f22e2 100644 --- a/core/server.go +++ b/core/server.go @@ -6,6 +6,8 @@ import ( "fmt" "log/slog" "net" + + "github.com/google/uuid" ) type Server struct { @@ -64,31 +66,47 @@ type Session struct { } func NewSession(ctx context.Context, c net.Conn, p Printer, l *slog.Logger) *Session { + sid := uuid.New() return &Session{ ctx: ctx, - l: l, - p: p, + l: l.With(slog.String("sid", sid.String())), c: c, } } +func (s *Session) bufferInput(commands chan string) { + scanner := bufio.NewScanner(s.c) + defer close(commands) + + for scanner.Scan() { + err := scanner.Err() + switch err { + case nil: + commands <- scanner.Text() + default: + s.l.With(slog.Any("error", scanner.Err())).Error("error scanning input") + return + } + } + + s.l.Debug("session terminated") +} + func (s *Session) Start() { s.l.Debug("starting telnet session") fmt.Fprint(s.c, "Welcome to Bing Bong.\n") - scanner := bufio.NewScanner(s.c) - var line string - for { - select { - case <-s.ctx.Done(): - s.l.Error("cancelled") + + commands := make(chan string) + go s.bufferInput(commands) + + for command := range commands { + s.l.With(slog.String("command", command)).Debug("command recieved") + _, err := fmt.Fprintf(s.c, "> %q\n", command) + if err != nil { + s.l.With( + slog.Any("error", err), + ).Error("connection closed on write") return - default: - if scanner.Scan() { - line = scanner.Text() - fmt.Fprintf(s.c, "> %q\n", line) - } - // a.L.Info("scanning input") - s.l.With(slog.String("input", line)).Info("received command") } } }