aboutsummaryrefslogtreecommitdiff
path: root/internal/net/conn.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-11 04:46:27 -0400
committerhistoria <[not public]>2026-06-11 08:58:37 +0000
commit1b9e2da3b3c438d8dc53d3489725dd5ba0022777 (patch)
tree62264f24420bf4cfaa734942c65cc8dd45ba3d3b /internal/net/conn.go
parent06c02a697e5daf8832a462de5970dd4c0e13a02c (diff)
downloadthehouseoficarus-1b9e2da3b3c438d8dc53d3489725dd5ba0022777.tar.gz
feat: web client, get/drop updates and fixes
Diffstat (limited to 'internal/net/conn.go')
-rw-r--r--internal/net/conn.go101
1 files changed, 101 insertions, 0 deletions
diff --git a/internal/net/conn.go b/internal/net/conn.go
new file mode 100644
index 0000000..e46031b
--- /dev/null
+++ b/internal/net/conn.go
@@ -0,0 +1,101 @@
+package net
+
+import (
+ "bufio"
+ "bytes"
+ "io"
+ "net"
+ "strings"
+)
+
+type Conn interface {
+ ReadMessage() (string, error)
+ io.Writer
+ io.Closer
+ SetEcho(bool) error
+}
+
+type tcpConn struct {
+ conn net.Conn
+ reader *bufio.Reader
+ echoOff bool
+}
+
+func newTCPConn(conn net.Conn) *tcpConn {
+ return &tcpConn{
+ conn: conn,
+ reader: bufio.NewReader(conn),
+ }
+}
+
+func (t *tcpConn) ReadMessage() (string, error) {
+ line, err := t.reader.ReadString('\n')
+ if err != nil {
+ return "", err
+ }
+ line = strings.TrimRight(line, "\r\n")
+ line = stripIAC(line)
+ if t.echoOff {
+ t.conn.Write([]byte("\r\n"))
+ }
+ return line, nil
+}
+
+func (t *tcpConn) Write(b []byte) (int, error) {
+ return t.conn.Write(b)
+}
+
+func (t *tcpConn) Close() error {
+ return t.conn.Close()
+}
+
+func (t *tcpConn) SetEcho(on bool) error {
+ t.echoOff = !on
+ if on {
+ return t.writeTelnetCmd(wont, echo)
+ }
+ return t.writeTelnetCmd(will, echo)
+}
+
+const (
+ iac = 255
+ will = 251
+ wont = 252
+ do = 253
+ dont = 254
+ sb = 250
+ se = 240
+ echo = 1
+)
+
+func (t *tcpConn) writeTelnetCmd(cmd, opt byte) error {
+ _, err := t.conn.Write([]byte{iac, cmd, opt})
+ return err
+}
+
+func stripIAC(s string) string {
+ b := []byte(s)
+ var out []byte
+ i := 0
+ iacSE := []byte{iac, se}
+ for i < len(b) {
+ if b[i] == iac && i+2 < len(b) {
+ if b[i+1] == sb {
+ end := bytes.Index(b[i+2:], iacSE)
+ if end >= 0 {
+ i += end + 4
+ continue
+ }
+ }
+ i += 3
+ continue
+ }
+ if b[i] == iac {
+ i++
+ continue
+ }
+ out = append(out, b[i])
+ i++
+ }
+ return string(out)
+}