/
lumberjackserver.go
161 lines (142 loc) · 3.51 KB
/
lumberjackserver.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package lumberjackserver
import (
"compress/zlib"
"crypto/rand"
"crypto/tls"
"encoding/binary"
"fmt"
"io"
"log"
"net"
"strconv"
)
type FileEvent struct {
Source string
Offset int
Host string
Text string
Fields map[string]string
}
type Server struct {
SSLCertificate string
SSLKey string
Port string
EventHandler func(f *FileEvent)
}
func NewServer(cert, key, port string) *Server {
s := &Server{SSLCertificate: cert, SSLKey: key, Port: port}
return s
}
func (s *Server) Serve() error {
var tlsconfig tls.Config
tlsconfig.MinVersion = tls.VersionTLS10
cert, err := tls.LoadX509KeyPair(s.SSLCertificate, s.SSLKey)
if err != nil {
return fmt.Errorf("Failed loading client ssl certificate: %s", err)
}
tlsconfig.Certificates = []tls.Certificate{cert}
tlsconfig.Rand = rand.Reader
service := fmt.Sprintf("0.0.0.0:%s", s.Port)
listener, err := tls.Listen("tcp", service, &tlsconfig)
if err != nil {
return err
}
log.Print("server: listening")
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("server: accept: %s", err)
break
}
defer conn.Close()
log.Printf("server: accepted from %s", conn.RemoteAddr())
go s.handleClient(conn)
}
return nil
}
func (s *Server) handleClient(conn net.Conn) {
defer conn.Close()
for {
log.Print("server: conn: waiting")
err := s.handleMessage(conn)
if err != nil {
log.Println(err)
break
}
}
log.Println("server: conn: closed")
}
func (s *Server) handleMessage(conn net.Conn) error {
header := make([]byte, 2)
var eventCount, compressedSize uint32
var reader io.Reader
reader = conn
for {
_, err := reader.Read(header)
if err != nil {
return fmt.Errorf("server: conn: handleMessage: %s", err)
}
log.Printf("server: conn: header: %s\n", string(header))
switch string(header) {
case "1W":
binary.Read(reader, binary.BigEndian, &eventCount)
log.Printf("server: conn: 1W length: %d\n", eventCount)
case "1C":
binary.Read(reader, binary.BigEndian, &compressedSize)
log.Printf("server: conn: 1C length: %d\n", compressedSize)
decompressor, err := zlib.NewReader(reader)
defer decompressor.Close()
if err != nil {
return fmt.Errorf("server: conn: handleMessage: %s", err)
}
reader = decompressor
case "1D":
err := s.handleData(reader, conn)
if err != nil {
return fmt.Errorf("server: conn: handleMessage: %s", err)
}
eventCount--
}
if eventCount == 0 {
return nil
}
}
}
func (s *Server) handleData(reader io.Reader, writer io.Writer) error {
var sequence, pairs uint32
binary.Read(reader, binary.BigEndian, &sequence)
binary.Read(reader, binary.BigEndian, &pairs)
log.Printf("server: conn: sequence: %d\n", sequence)
event := FileEvent{Fields: make(map[string]string)}
var i uint32
for i = 0; i < pairs; i++ {
var key_len, val_len uint32
binary.Read(reader, binary.BigEndian, &key_len)
key := make([]byte, key_len)
reader.Read(key)
binary.Read(reader, binary.BigEndian, &val_len)
val := make([]byte, val_len)
reader.Read(val)
//log.Printf("[%d] %s : %s", i, string(key), string(val))
switch string(key) {
case "file":
event.Source = string(val)
case "host":
event.Host = string(val)
case "offset":
offset, err := strconv.Atoi(string(val))
if err != nil {
return err
}
event.Offset = offset
case "line":
event.Text = string(val)
default:
event.Fields[string(key)] = string(val)
}
}
s.EventHandler(&event)
writer.Write([]byte("1A"))
binary.Write(writer, binary.BigEndian, sequence)
return nil
}