-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
84 lines (75 loc) · 1.63 KB
/
server.go
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
package byor
import (
"errors"
"io"
"net"
"sync"
"syscall"
"time"
)
var slog = newLogger("[SERVER]")
func Server(port string) error {
var wg sync.WaitGroup
quit := catchSignals()
addr, addrErr := net.ResolveTCPAddr("tcp", port)
if addrErr != nil {
return addrErr
}
tcpListener, listenerErr := net.ListenTCP("tcp", addr)
if listenerErr != nil {
return listenerErr
}
slog.debugf("Listening on port %v", port)
for {
select {
case <-quit:
slog.debugf("Got close siginal, waiting for connections to drain")
tcpListener.Close()
wg.Wait()
return nil
default:
tcpListener.SetDeadline(time.Now().Add(1e9))
tcpConn, connErr := tcpListener.AcceptTCP()
if connErr != nil {
if opErr, ok := connErr.(*net.OpError); !ok || !opErr.Timeout() {
slog.errorf("%v", connErr)
}
continue
}
wg.Add(1)
go func(conn net.Conn) {
defer conn.Close()
defer wg.Done()
if hErr := connHandler(conn); hErr != nil {
slog.errorf("Connection closed %v", hErr)
return
}
}(tcpConn)
}
}
}
func connHandler(conn net.Conn) error {
for {
data, dataErr := Decoder(conn)
if dataErr != nil {
if errors.Is(dataErr, io.EOF) {
return dataErr
}
slog.errorf("Reading from connection %v", dataErr)
continue
}
status, reply := requestHandler(data)
res, resErr := composeRes(status, reply)
if resErr != nil {
slog.errorf("Composing response %v", resErr)
res = validResponseOnComposeError()
}
if wErr := Encoder(conn, res); wErr != nil {
if errors.Is(wErr, syscall.EPIPE) {
return wErr
}
slog.errorf("Writing to connection %v", wErr)
continue
}
}
}