aboutsummaryrefslogtreecommitdiff
path: root/cmd/server/server.go
blob: 76fc1e57d982634c7143b3a1d8896724ab5ffc66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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", "")

	ws, err := db.SelectDict(context.Background(), q, 10)
	if err != nil {
		slog.Error("Error selecting", "error", err)
		return
	}

	for _, w := range ws {
		fmt.Fprintf(conn, "%s\n%s\n\n", w.Word, w.Line)
	}
}