-
Notifications
You must be signed in to change notification settings - Fork 1
/
transport.go
169 lines (132 loc) · 3.83 KB
/
transport.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
162
163
164
165
166
167
168
169
package syslog5424 // import "github.com/nathanaelle/syslog5424/v2"
import (
"bytes"
"strconv"
)
type (
// Encode frame in NULL terminated frame
tZeroEnded struct{}
// Encode frame in LF terminated frame
tLFEnded struct{}
// Encode frame in RFC 5425 formated frame
// RFC 5425 Format format is :
// len([]byte) ' ' []byte
tRFC5425 struct{}
tGuess struct{}
// Transport describe a generic way to encode and decode syslog 5424 on an connexion
Transport interface {
// Set the sub conn where to write the transport-encoded data
Encode([]byte) []byte
// Decode the prefix in case of transport that use an encoding header
PrefixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error)
// Decode the suffix in case of transport that use an encoding terminaison
SuffixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error)
String() string
}
)
var (
// TransportZeroEnded is commonly used transport with "unix" and "unixgram"
TransportZeroEnded Transport = tZeroEnded{}
// TransportLFEnded is commonly used transport with "tcp" "tcp4" and "tcp6"
TransportLFEnded Transport = tLFEnded{}
// TransportRFC5425 is performant transport specified in RFC 5425
TransportRFC5425 Transport = tRFC5425{}
)
func (t tZeroEnded) String() string {
return "zero ended transport"
}
func (t tLFEnded) String() string {
return "lf ended transport"
}
func (t tRFC5425) String() string {
return "rfc 5425 transport"
}
func (t tZeroEnded) PrefixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
return buffer, nil, nil
}
func (t tLFEnded) PrefixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
return buffer, nil, nil
}
func (t tRFC5425) PrefixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
if len(buffer) < 20 {
return nil, nil, nil
}
sepPos := bytes.IndexByte(buffer, ' ')
if sepPos <= 0 {
return nil, nil, ErrTransportNoHeader
}
lenMsg, err := strconv.Atoi(string(buffer[0:sepPos]))
if err != nil {
return nil, nil, ErrTransportInvHeader
}
start := sepPos + 1
lenBuff := start + lenMsg
if len(buffer) < lenBuff {
if atEOF {
return buffer[start:], nil, ErrTransportIncomplete
}
return nil, nil, nil
}
return buffer[start:lenBuff], buffer[lenBuff:], nil
}
func (t tZeroEnded) SuffixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
if i := bytes.IndexByte(buffer, byte(0)); i >= 0 {
return buffer[0:i], buffer[i+1:], nil
}
// at EOF act like \0 is implicit
if atEOF {
return buffer, nil, nil
}
return buffer, nil, nil
}
func (t tLFEnded) SuffixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
if i := bytes.IndexByte(buffer, '\n'); i >= 0 {
return buffer[0:i], buffer[i+1:], nil
}
if atEOF {
return buffer, nil, ErrTransportIncomplete
}
return buffer, nil, nil
}
func (t tRFC5425) SuffixStrip(buffer []byte, atEOF bool) (data, rest []byte, err error) {
if buffer == nil || len(buffer) == 0 {
return nil, nil, nil
}
return buffer, nil, nil
}
// Write a NULL terminated message.
// see (Conn interface)[#Conn]
func (t tZeroEnded) Encode(d []byte) []byte {
return append(d, byte(0))
}
// Write a LF terminated message
// see (Conn interface)[#Conn]
func (t tLFEnded) Encode(d []byte) []byte {
return append(d, '\n')
}
// Write a RFC 5425 formated message
// see (Conn interface)[#Conn]
func (t tRFC5425) Encode(d []byte) []byte {
l := len(d)
h := []byte(strconv.Itoa(l))
ret := make([]byte, l+len(h)+1)
copy(ret[0:len(h)], h[:])
ret[len(h)] = ' '
copy(ret[len(h)+1:], d[:])
return ret
}