1
+ // vim: set ft=javascript tabstop=4 softtabstop=4 shiftwidth=4 autoindent:
1
2
var dgram = require ( 'dgram' )
2
3
var debug = require ( 'debug' ) ( 'syslogd' )
3
4
@@ -11,6 +12,7 @@ function Syslogd(fn, opt) {
11
12
}
12
13
this . opt = opt || { }
13
14
this . handler = fn
15
+
14
16
this . server = dgram . createSocket ( 'udp4' )
15
17
}
16
18
@@ -96,3 +98,176 @@ function parser(msg, rinfo) {
96
98
}
97
99
98
100
exports . parser = parser
101
+
102
+ /*
103
+ * SOCK_STREAM service
104
+ */
105
+ const net = require ( 'net' )
106
+
107
+ function SimpleStreamService ( messageReceived , options ) {
108
+ return new StreamService ( messageReceived , options ) ;
109
+ }
110
+
111
+ function StreamService ( fn , opt ) {
112
+ this . opt = opt || { }
113
+ this . handler = fn
114
+
115
+ this . server = net . createServer ( ( connection ) => {
116
+ debug ( 'New connection from ' + connection . remoteAddress + ":" + connection . remotePort )
117
+ var state = new ConnectionState ( this , connection ) ;
118
+ connection . on ( 'data' , ( buffer ) => { state . more_data ( buffer ) } )
119
+ connection . on ( 'end' , ( ) => { state . closed ( ) } )
120
+ } )
121
+ return this ;
122
+ }
123
+
124
+ StreamService . prototype . listen = function ( port , callback ) {
125
+ var server = this . server
126
+ callback = callback || noop
127
+ this . port = port || 514 // default is 514
128
+ debug ( 'Binding to ' + this . port )
129
+ var me = this
130
+ server
131
+ . on ( 'error' , function ( err ) {
132
+ debug ( 'binding error: %o' , err )
133
+ callback ( err )
134
+ } )
135
+ . on ( 'listening' , function ( ) {
136
+ debug ( 'tcp binding ok' )
137
+ me . port = server . address ( ) . port
138
+ callback ( null , me )
139
+ } )
140
+ . listen ( port , this . opt . address )
141
+
142
+ return this
143
+ }
144
+
145
+ class ConnectionState {
146
+ constructor ( service , connection ) {
147
+ this . service = service
148
+ this . info = {
149
+ address : connection . remoteAddress ,
150
+ family : connection . family ,
151
+ port : connection . remotePort
152
+ }
153
+ this . frameParser = new FrameParser ( ( frame ) => {
154
+ this . dispatch_message ( frame )
155
+ } )
156
+ }
157
+
158
+ more_data ( buffer ) {
159
+ this . frameParser . feed ( buffer )
160
+ }
161
+
162
+ dispatch_message ( frame ) {
163
+ let clientInfo = {
164
+ address : this . info . address ,
165
+ family : this . info . family ,
166
+ family : this . info . remotePort ,
167
+ size : frame . length
168
+ }
169
+ let message = parser ( frame , clientInfo )
170
+ this . service . handler ( message )
171
+ }
172
+
173
+ closed ( ) {
174
+ this . frameParser . done ( )
175
+ }
176
+ }
177
+
178
+ let FRAME_TYPE_UNKNOWN = 0 ;
179
+ let FRAME_TYPE_NEWLINE = 1 ;
180
+ let FRAME_TYPE_OCTET = 2 ;
181
+
182
+ class FrameParser {
183
+ constructor ( callback ) {
184
+ this . buffer = Buffer . from ( "" )
185
+ this . callback = callback ;
186
+ this . frame_state = FRAME_TYPE_UNKNOWN ;
187
+ }
188
+
189
+ feed ( data ) {
190
+ this . buffer = Buffer . concat ( [ this . buffer , data ] )
191
+ this . check_framing ( )
192
+ }
193
+
194
+ done ( ) {
195
+ if ( this . buffer . length > 0 ) {
196
+ this . callback ( this . buffer . toString ( ) )
197
+ }
198
+ this . buffer = Buffer . from ( "" )
199
+ }
200
+
201
+ check_framing ( ) {
202
+ if ( this . frame_state == FRAME_TYPE_UNKNOWN ) {
203
+ this . decide_on_frame_type ( ) ;
204
+ } else if ( this . frame_state == FRAME_TYPE_NEWLINE ) {
205
+ this . check_newline_framing ( ) ;
206
+ } else if ( this . frame_state == FRAME_TYPE_OCTET ) {
207
+ this . check_octet_frame ( )
208
+ } else {
209
+ throw "Invalid farme state" ;
210
+ }
211
+ }
212
+
213
+ decide_on_frame_type ( ) {
214
+ // do nothing if buffer is too short
215
+ if ( this . buffer . length < 8 ) {
216
+ return
217
+ }
218
+ // shrink our check buffer
219
+ let check = this . buffer . slice ( 0 , 8 )
220
+ // Do we have spaces?
221
+ let space = check . indexOf ( " " )
222
+ if ( space == - 1 ) {
223
+ this . frame_state = FRAME_TYPE_NEWLINE
224
+ return this . check_framing ( )
225
+ }
226
+
227
+ // Check output if we can convert it to a number
228
+ let size = parseInt ( check . slice ( 0 , space ) , 10 )
229
+ if ( isNaN ( size ) || size < 2 ) {
230
+ this . frame_state = FRAME_TYPE_NEWLINE
231
+ return this . check_framing ( )
232
+ }
233
+
234
+ // Octet framing
235
+ this . octets = size
236
+ this . frame_state = FRAME_TYPE_OCTET
237
+ this . buffer = this . buffer . slice ( space + 1 )
238
+ return this . check_framing ( )
239
+ }
240
+
241
+ check_newline_framing ( ) {
242
+ let indexOfNewLine = this . buffer . indexOf ( "\n" )
243
+ if ( indexOfNewLine == - 1 ) { return ; }
244
+
245
+ let frame = this . buffer . slice ( 0 , indexOfNewLine )
246
+ this . buffer = this . buffer . slice ( indexOfNewLine + 1 )
247
+
248
+ this . _emit_and_reset ( frame )
249
+ }
250
+
251
+ check_octet_frame ( ) {
252
+ let size = this . octets
253
+ if ( ! size ) { throw "Not currently in octet strategy" }
254
+
255
+ if ( this . buffer . length < size ) { return }
256
+
257
+ let frame = this . buffer . slice ( 0 , size )
258
+ this . buffer = this . buffer . slice ( size )
259
+
260
+ this . _emit_and_reset ( frame )
261
+ }
262
+
263
+ _emit_and_reset ( frame ) {
264
+ this . callback ( frame . toString ( ) )
265
+
266
+ this . frame_state = FRAME_TYPE_UNKNOWN
267
+ this . check_framing ( )
268
+ }
269
+ }
270
+
271
+ exports . StreamService = SimpleStreamService
272
+ exports . FrameParser = FrameParser
273
+
0 commit comments