From 2c8efcea4bba5e9998dddfa620d3433d880d8374 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Fri, 5 Dec 2025 23:18:37 -0600 Subject: [PATCH 1/3] add output to TCP server --- tcp-server.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/tcp-server.go b/tcp-server.go index 78591d4..c6e488b 100644 --- a/tcp-server.go +++ b/tcp-server.go @@ -1,10 +1,13 @@ package showbridge import ( + "errors" "fmt" "log/slog" "net" + "slices" "sync" + "syscall" "time" "github.com/jwetzell/showbridge-go/internal/framing" @@ -18,6 +21,8 @@ type TCPServer struct { router *Router quit chan interface{} wg sync.WaitGroup + connections []net.Conn + connectionsMu sync.RWMutex } func init() { @@ -78,6 +83,9 @@ func (ts *TCPServer) RegisterRouter(router *Router) { } func (ts *TCPServer) handleClient(client net.Conn) { + ts.connectionsMu.Lock() + ts.connections = append(ts.connections, client) + ts.connectionsMu.Unlock() slog.Debug("connection accepted", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) defer client.Close() var framer framing.Framer @@ -105,11 +113,34 @@ ClientRead: if err != nil { //NOTE(jwetzell) we hit deadline - if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { - continue ClientRead + if opErr, ok := err.(*net.OpError); ok { + if opErr.Timeout() { + continue ClientRead + } + fmt.Println(opErr.Err) + if errors.Is(opErr, syscall.ECONNRESET) { + ts.connectionsMu.Lock() + for i := 0; i < len(ts.connections); i++ { + if ts.connections[i] == client { + ts.connections = slices.Delete(ts.connections, i, i+1) + break + } + } + slog.Debug("connection closed", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + ts.connectionsMu.Unlock() + } } + if err.Error() == "EOF" { + ts.connectionsMu.Lock() + for i := 0; i < len(ts.connections); i++ { + if ts.connections[i] == client { + ts.connections = slices.Delete(ts.connections, i, i+1) + break + } + } slog.Debug("connection closed", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + ts.connectionsMu.Unlock() } return } @@ -168,5 +199,24 @@ AcceptLoop: } func (ts *TCPServer) Output(payload any) error { - return fmt.Errorf("net.tcp.server output is not implemented") + payloadBytes, ok := payload.([]byte) + + if !ok { + return fmt.Errorf("net.tcp.server is only able to output bytes") + } + ts.connectionsMu.Lock() + errorString := "" + + for _, connection := range ts.connections { + _, err := connection.Write(payloadBytes) + if err != nil { + errorString += fmt.Sprintf("%s\n", err.Error()) + } + } + ts.connectionsMu.Unlock() + + if errorString == "" { + return nil + } + return fmt.Errorf("%s", errorString) } From 51a62f7fb2d4cd053a624f22231a07d44536cc22 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Sat, 6 Dec 2025 08:23:40 -0600 Subject: [PATCH 2/3] cleanup --- tcp-server.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tcp-server.go b/tcp-server.go index c6e488b..3379146 100644 --- a/tcp-server.go +++ b/tcp-server.go @@ -112,12 +112,11 @@ ClientRead: byteCount, err := client.Read(buffer) if err != nil { - //NOTE(jwetzell) we hit deadline if opErr, ok := err.(*net.OpError); ok { + //NOTE(jwetzell) we hit deadline if opErr.Timeout() { continue ClientRead } - fmt.Println(opErr.Err) if errors.Is(opErr, syscall.ECONNRESET) { ts.connectionsMu.Lock() for i := 0; i < len(ts.connections); i++ { @@ -126,7 +125,7 @@ ClientRead: break } } - slog.Debug("connection closed", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + slog.Debug("connection reset", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) ts.connectionsMu.Unlock() } } @@ -139,7 +138,7 @@ ClientRead: break } } - slog.Debug("connection closed", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + slog.Debug("stream ended", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) ts.connectionsMu.Unlock() } return From aa3a1032f3cb1db0ee8d50d563df7a2fd577e4a3 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Sat, 6 Dec 2025 08:39:34 -0600 Subject: [PATCH 3/3] logging tweaks --- tcp-server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tcp-server.go b/tcp-server.go index 3379146..89e0a4a 100644 --- a/tcp-server.go +++ b/tcp-server.go @@ -86,7 +86,7 @@ func (ts *TCPServer) handleClient(client net.Conn) { ts.connectionsMu.Lock() ts.connections = append(ts.connections, client) ts.connectionsMu.Unlock() - slog.Debug("connection accepted", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + slog.Debug("net.tcp.server connection accepted", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) defer client.Close() var framer framing.Framer @@ -125,7 +125,7 @@ ClientRead: break } } - slog.Debug("connection reset", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + slog.Debug("net.tcp.server connection reset", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) ts.connectionsMu.Unlock() } } @@ -138,7 +138,7 @@ ClientRead: break } } - slog.Debug("stream ended", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) + slog.Debug("net.tcp.server stream ended", "id", ts.config.Id, "remoteAddr", client.RemoteAddr().String()) ts.connectionsMu.Unlock() } return