package server import ( "context" "fmt" "io" "log/slog" "net" "strings" "git.gabrielgio.me/dict/db" "github.com/urfave/cli/v2" ) var ServeCommand = &cli.Command{ Name: "serve", Usage: "Start a simple tcp server to ansower queries", Flags: []cli.Flag{ &cli.StringFlag{ Name: "addr", Value: "/tmp/dict.sock", Usage: "Address", }, &cli.StringFlag{ Name: "database", Value: "main.dict", Usage: "Dictionary database location", }, }, Action: func(cCtx *cli.Context) error { addr := cCtx.String("addr") database := cCtx.String("database") return Server(context.Background(), addr, database) }, } func Server(ctx context.Context, addr, database string) error { // Listen for incoming connections on port 8080 db, err := db.Open(database) if err != nil { return fmt.Errorf("Error openning datbase:%w", err) } ln, err := net.Listen("unix", addr) if err != nil { return err } defer ln.Close() // Accept incoming connections and handle them for { conn, err := ln.Accept() if err != nil { slog.Error("Error accepting conn", "error", err) continue } slog.Info("Connection accepeted") go handleConnection(conn, db) } } func handleConnection(conn net.Conn, db *db.DB) { defer conn.Close() // Read incoming data buf := make([]byte, 0, 4096) // big buffer tmp := make([]byte, 256) // using small tmo buffer for demonstrating for { n, err := conn.Read(tmp) if err != nil { if err != io.EOF { slog.Error("Error reading conn", "error", err) return } break } buf = append(buf, tmp[:n]...) } q := strings.ReplaceAll(string(buf), "\n", "") slog.Info("Query", "query", q) ws, err := db.SelectDict(context.Background(), q, 10) if err != nil { slog.Error("Error selecting", "error", err) return } slog.Info("Count", "q", len(ws)) for _, w := range ws { fmt.Fprintf(conn, "%s\n%s\n\n", w.Word, w.Line) } }