package server import ( "context" "fmt" "log" "net" "codeberg.org/snonux/gorum/internal/config" "codeberg.org/snonux/gorum/internal/iorw" ) type handlerCb func(message string) string func tcpServerRun(ctx context.Context, conf config.Config, cb handlerCb) error { listener, err := net.Listen("tcp", conf.Address) if err != nil { return fmt.Errorf("error starting TCP server: %w", err) } defer listener.Close() log.Println("server: listening on", conf.Address) for { conn, err := listener.Accept() if err != nil { log.Println("server: error accepting connection:", err) continue } if !conf.RelaxedMode && !conf.IsNodeWithLookup(conn.RemoteAddr().String(), net.LookupIP) { log.Println("server: denying connection, peer not a node:", conn.RemoteAddr().String()) conn.Close() continue } log.Println("server: client connected:", conn.RemoteAddr().String()) go handleConnection(ctx, conn, cb) } } func handleConnection(ctx context.Context, conn net.Conn, cb handlerCb) { defer conn.Close() remoteAddr := conn.RemoteAddr().String() for { select { case <-ctx.Done(): log.Println("server: context done, disconnecting client:", remoteAddr) return default: message, err := iorw.ReadStr(conn) if err != nil { log.Println("server: unable to read message", remoteAddr, err) return } log.Println("server: received message", message, "from", remoteAddr) response := cb(message) if err := iorw.WriteStr(conn, response); err != nil { log.Println("error:", err) } } } }