-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
113 lines (102 loc) · 2.53 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Package syslog implements a syslog server library. It is based on RFC 3164,
// as such it does not properly parse packets with an RFC 5424 header format.
package syslog
import (
"log"
"net"
"os"
"strings"
"unicode"
)
// Server is the wrapper for a syslog server.
type Server struct {
conns []net.PacketConn
handlers []Handler
shutdown bool
l FatalLogger
}
// NewServer creates an idle server.
func NewServer() *Server {
return &Server{l: log.New(os.Stderr, "", log.LstdFlags)}
}
// SetLogger sets logger for server errors. A running server is rather quiet and
// logs only fatal errors using FatalLogger interface. By default standard Go
// logger is used so errors are writen to stderr and after that whole
// application is halted. Using SetLogger you can change this behavior (log
// erross elsewhere and don't halt whole application).
func (s *Server) SetLogger(l FatalLogger) {
s.l = l
}
// AddHandler adds h to internal ordered list of handlers
func (s *Server) AddHandler(h Handler) {
s.handlers = append(s.handlers, h)
}
// Listen starts gorutine that receives syslog messages on specified address.
// addr can be a path (for unix domain sockets) or host:port (for UDP).
func (s *Server) Listen(addr string) error {
var c net.PacketConn
if strings.IndexRune(addr, ':') != -1 {
a, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return err
}
c, err = net.ListenUDP("udp", a)
if err != nil {
return err
}
} else {
a, err := net.ResolveUnixAddr("unixgram", addr)
if err != nil {
return err
}
c, err = net.ListenUnixgram("unixgram", a)
if err != nil {
return err
}
}
s.conns = append(s.conns, c)
go s.receiver(c)
return nil
}
// Shutdown stops server.
func (s *Server) Shutdown() {
s.shutdown = true
for _, c := range s.conns {
err := c.Close()
if err != nil {
s.l.Fatalln(err)
}
}
s.passToHandlers(nil)
s.conns = nil
s.handlers = nil
}
func isNotAlnum(r rune) bool {
return !(unicode.IsLetter(r) || unicode.IsNumber(r))
}
func isNulCrLf(r rune) bool {
return r == 0 || r == '\r' || r == '\n'
}
func (s *Server) passToHandlers(m SyslogMessage) {
for _, h := range s.handlers {
m = h.Handle(m)
if m == nil {
break
}
}
}
func (s *Server) receiver(c net.PacketConn) {
// make packet buffer the same size as logspout
buf := make([]byte, 1048576)
for {
n, _, err := c.ReadFrom(buf)
if err != nil {
if !s.shutdown {
s.l.Fatalln("Read error:", err)
}
return
}
// pass along the incoming syslog message
s.passToHandlers(&Message{string(buf[:n])})
}
}