log-courier 1.3 → 1.6.pre.40.g3efb33c

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 645bd508ce891c3fb1fd69c4a414758fdc55c867
4
- data.tar.gz: c4b14fb6f9cc1b75ac2c886d0162b543246ef5c5
3
+ metadata.gz: 3d3903076cfa365c6fc3b3732c4990d84b7dcb13
4
+ data.tar.gz: 391ef46aae7fa0d1da6719a8fa6913b61fa4d6e9
5
5
  SHA512:
6
- metadata.gz: 2f512338b7e7a11fff7293a9006ef5a924596f5b7f40863e5f12a68297588e1969628aa6b3730b30bac9464071d9da63186aac9c460bfbe8f92219f42f6731e2
7
- data.tar.gz: 736be3625601a89409beee281f432e6450af0a76aa040eb916e848512cfcb195b8bd6b0c6ef013e0a0757fe5237f35acdf9bd273ffe34a9c765e5f81ac4ab841
6
+ metadata.gz: db9e733ccac3f49b2a16658ebe60783e1249831f1bfb3225520ac6d325e6a99e4aa33c419276cb27ceb4598720bbf7caea8b65eb5a9f56d7fc35386d8655c6ab
7
+ data.tar.gz: a1be65639cbd57b7c0c1e503d122d1498bcb70c90cb015b9e74cbf7a6d756932c2019e2b381977711c8840f5f5fff30d508f8c57cd8b6c5984ac4f5dc7cd4254
@@ -25,6 +25,7 @@ require 'zlib'
25
25
  class NativeException; end
26
26
 
27
27
  module LogCourier
28
+ class TimeoutError < StandardError; end
28
29
  class ShutdownSignal < StandardError; end
29
30
  class ProtocolError < StandardError; end
30
31
 
@@ -77,12 +78,14 @@ module LogCourier
77
78
  lines = @sequence_len - @last_sequence
78
79
  @last_sequence = sequence
79
80
  @payload = nil
81
+ @events = []
80
82
  return lines, true
81
83
  end
82
84
 
83
85
  lines = sequence - @last_sequence
84
86
  @last_sequence = sequence
85
87
  @payload = nil
88
+ @events.shift(lines)
86
89
  return lines, false
87
90
  end
88
91
  end
@@ -92,15 +95,26 @@ module LogCourier
92
95
  def initialize(options = {})
93
96
  @options = {
94
97
  logger: nil,
98
+ transport: 'tls',
95
99
  spool_size: 1024,
96
- idle_timeout: 5
100
+ idle_timeout: 5,
101
+ port: nil,
102
+ addresses: [],
97
103
  }.merge!(options)
98
104
 
99
105
  @logger = @options[:logger]
100
- @logger['plugin'] = 'output/courier'
106
+ @logger['plugin'] = 'output/courier' unless @logger.nil?
101
107
 
102
- require 'log-courier/client_tls'
103
- @client = ClientTls.new(@options)
108
+ case @options[:transport]
109
+ when 'tcp', 'tls'
110
+ require 'log-courier/client_tcp'
111
+ @client = ClientTcp.new(@options)
112
+ else
113
+ fail 'output/courier: \'transport\' must be tcp or tls'
114
+ end
115
+
116
+ fail 'output/courier: \'addresses\' must contain at least one address' if @options[:addresses].empty?
117
+ fail 'output/courier: \'addresses\' only supports a single address at this time' if @options[:addresses].length > 1
104
118
 
105
119
  @event_queue = EventQueue.new @options[:spool_size]
106
120
  @pending_payloads = {}
@@ -115,6 +129,16 @@ module LogCourier
115
129
  run_spooler
116
130
  end
117
131
 
132
+ # TODO: Make these configurable?
133
+ @keepalive_timeout = 1800
134
+ @network_timeout = 30
135
+
136
+ # TODO: Make pending payload max configurable?
137
+ @max_pending_payloads = 100
138
+
139
+ @retry_payload = nil
140
+ @received_payloads = Queue.new
141
+
118
142
  @pending_ping = false
119
143
 
120
144
  # Start the IO thread
@@ -130,11 +154,17 @@ module LogCourier
130
154
  return
131
155
  end
132
156
 
133
- def shutdown
134
- # Raise a shutdown signal in the spooler and wait for it
135
- @spooler_thread.raise ShutdownSignal
136
- @io_thread.raise ShutdownSignal
137
- @spooler_thread.join
157
+ def shutdown(force=false)
158
+ if force
159
+ # Raise a shutdown signal in the spooler and wait for it
160
+ @spooler_thread.raise ShutdownSignal
161
+ @spooler_thread.join
162
+ @io_thread.raise ShutdownSignal
163
+ else
164
+ @event_queue.push nil
165
+ @spooler_thread.join
166
+ @io_control << ['!', nil]
167
+ end
138
168
  @io_thread.join
139
169
  return @pending_payloads.length == 0
140
170
  end
@@ -150,7 +180,13 @@ module LogCourier
150
180
  begin
151
181
  loop do
152
182
  event = @event_queue.pop next_flush - Time.now.to_i
183
+
184
+ if event.nil?
185
+ raise ShutdownSignal
186
+ end
187
+
153
188
  spooled.push(event)
189
+
154
190
  break if spooled.length >= @options[:spool_size]
155
191
  end
156
192
  rescue TimeoutError
@@ -158,12 +194,19 @@ module LogCourier
158
194
  next if spooled.length == 0
159
195
  end
160
196
 
197
+ if spooled.length >= @options[:spool_size]
198
+ @logger.debug 'Flushing full spool', :events => spooled.length unless @logger.nil?
199
+ else
200
+ @logger.debug 'Flushing spool due to timeout', :events => spooled.length unless @logger.nil?
201
+ end
202
+
161
203
  # Pass through to io_control but only if we're ready to send
162
204
  @send_mutex.synchronize do
163
- @send_cond.wait(@send_mutex) unless @send_ready
205
+ @send_cond.wait(@send_mutex) until @send_ready
164
206
  @send_ready = false
165
- @io_control << ['E', spooled]
166
207
  end
208
+
209
+ @io_control << ['E', spooled]
167
210
  end
168
211
  return
169
212
  rescue ShutdownSignal
@@ -171,118 +214,17 @@ module LogCourier
171
214
  end
172
215
 
173
216
  def run_io
174
- # TODO: Make keepalive configurable?
175
- @keepalive_timeout = 1800
176
-
177
- # TODO: Make pending payload max configurable?
178
- max_pending_payloads = 100
179
-
180
- retry_payload = nil
181
-
182
- can_send = true
183
-
184
217
  loop do
185
218
  # Reconnect loop
186
219
  @client.connect @io_control
187
220
 
188
- reset_keepalive
221
+ @timeout = Time.now.to_i + @keepalive_timeout
189
222
 
190
- # Capture send exceptions
191
- begin
192
- # IO loop
193
- loop do
194
- catch :keepalive do
195
- begin
196
- action = @io_control.pop @keepalive_next - Time.now.to_i
197
-
198
- # Process the action
199
- case action[0]
200
- when 'S'
201
- # If we're flushing through the pending, pick from there
202
- unless retry_payload.nil?
203
- # Regenerate data if we need to
204
- retry_payload.data = buffer_jdat_data(retry_payload.events, retry_payload.nonce) if retry_payload.data == nil
205
-
206
- # Send and move onto next
207
- @client.send 'JDAT', retry_payload.data
208
-
209
- retry_payload = retry_payload.next
210
- throw :keepalive
211
- end
212
-
213
- # Ready to send, allow spooler to pass us something
214
- @send_mutex.synchronize do
215
- @send_ready = true
216
- @send_cond.signal
217
- end
218
-
219
- can_send = true
220
- when 'E'
221
- # If we have too many pending payloads, pause the IO
222
- if @pending_payloads.length + 1 >= max_pending_payloads
223
- @client.pause_send
224
- end
225
-
226
- # Received some events - send them
227
- send_jdat action[1]
228
-
229
- # The send action will trigger another "S" if we have more send buffer
230
- can_send = false
231
- when 'R'
232
- # Received a message
233
- signature, message = action[1..2]
234
- case signature
235
- when 'PONG'
236
- process_pong message
237
- when 'ACKN'
238
- process_ackn message
239
- else
240
- # Unknown message - only listener is allowed to respond with a "????" message
241
- # TODO: What should we do? Just ignore for now and let timeouts conquer
242
- end
243
- when 'F'
244
- # Reconnect, an error occurred
245
- break
246
- end
247
- rescue TimeoutError
248
- # Keepalive timeout hit, send a PING unless we were awaiting a PONG
249
- if @pending_ping
250
- # Timed out, break into reconnect
251
- fail TimeoutError
252
- end
253
-
254
- # Is send full? can_send will be false if so
255
- # We should've started receiving ACK by now so time out
256
- fail TimeoutError unless can_send
257
-
258
- # Send PING
259
- send_ping
260
-
261
- # We may have filled send buffer
262
- can_send = false
263
- end
264
- end
265
-
266
- # Reset keepalive timeout
267
- reset_keepalive
268
- end
269
- rescue ProtocolError => e
270
- # Reconnect required due to a protocol error
271
- @logger.warn 'Protocol error', :error => e.message unless @logger.nil?
272
- rescue TimeoutError
273
- # Reconnect due to timeout
274
- @logger.warn 'Timeout occurred' unless @logger.nil?
275
- rescue ShutdownSignal
276
- # Shutdown, break out
277
- break
278
- rescue StandardError, NativeException => e
279
- # Unknown error occurred
280
- @logger.warn e, :hint => 'Unknown error' unless @logger.nil?
281
- end
223
+ run_io_loop
282
224
 
283
225
  # Disconnect and retry payloads
284
226
  @client.disconnect
285
- retry_payload = @first_payload
227
+ @retry_payload = @first_payload
286
228
 
287
229
  # TODO: Make reconnect time configurable?
288
230
  sleep 5
@@ -290,11 +232,164 @@ module LogCourier
290
232
 
291
233
  @client.disconnect
292
234
  return
235
+ rescue ShutdownSignal
236
+ # Ensure disconnected
237
+ @client.disconnect
293
238
  end
294
239
 
295
- def reset_keepalive
296
- @keepalive_next = Time.now.to_i + @keepalive_timeout
297
- return
240
+ def run_io_loop()
241
+ io_stop = false
242
+ can_send = false
243
+
244
+ # IO loop
245
+ loop do
246
+ begin
247
+ action = @io_control.pop @timeout - Time.now.to_i
248
+
249
+ # Process the action
250
+ case action[0]
251
+ when 'S'
252
+ # If we're flushing through the pending, pick from there
253
+ unless @retry_payload.nil?
254
+ @logger.debug 'Send is ready, retrying previous payload' unless @logger.nil?
255
+
256
+ # Regenerate data if we need to
257
+ @retry_payload.generate if @retry_payload.payload.nil?
258
+
259
+ # Send and move onto next
260
+ @client.send 'JDAT', @retry_payload.payload
261
+
262
+ @retry_payload = @retry_payload.next
263
+
264
+ # If first send, exit idle mode
265
+ if @retry_payload == @first_payload
266
+ @timeout = Time.now.to_i + @network_timeout
267
+ end
268
+ next
269
+ end
270
+
271
+ # Ready to send, allow spooler to pass us something if we don't
272
+ # have something already
273
+ if @received_payloads.length != 0
274
+ @logger.debug 'Send is ready, using events from backlog' unless @logger.nil?
275
+ send_payload @received_payloads.pop()
276
+ else
277
+ @logger.debug 'Send is ready, requesting events' unless @logger.nil?
278
+
279
+ can_send = true
280
+
281
+ @send_mutex.synchronize do
282
+ @send_ready = true
283
+ @send_cond.signal
284
+ end
285
+ end
286
+ when 'E'
287
+ # Were we expecting a payload? Store it if not
288
+ if can_send
289
+ @logger.debug 'Sending events', :events => action[1].length unless @logger.nil?
290
+ send_payload action[1]
291
+ can_send = false
292
+ else
293
+ @logger.debug 'Events received when not ready; saved to backlog' unless @logger.nil?
294
+ @received_payloads.push action[1]
295
+ end
296
+ when 'R'
297
+ # Received a message
298
+ signature, message = action[1..2]
299
+ case signature
300
+ when 'PONG'
301
+ process_pong message
302
+ when 'ACKN'
303
+ process_ackn message
304
+ else
305
+ # Unknown message - only listener is allowed to respond with a "????" message
306
+ # TODO: What should we do? Just ignore for now and let timeouts conquer
307
+ end
308
+
309
+ # Any pending payloads left?
310
+ if @pending_payloads.length == 0
311
+ # Handle shutdown
312
+ if io_stop
313
+ raise ShutdownSignal
314
+ end
315
+
316
+ # Enter idle mode
317
+ @timeout = Time.now.to_i + @keepalive_timeout
318
+ else
319
+ # Set network timeout
320
+ @timeout = Time.now.to_i + @network_timeout
321
+ end
322
+ when 'F'
323
+ # Reconnect, an error occurred
324
+ break
325
+ when '!'
326
+ @logger.debug 'Shutdown request received' unless @logger.nil?
327
+
328
+ # Shutdown request received
329
+ if @pending_payloads.length == 0
330
+ raise ShutdownSignal
331
+ end
332
+
333
+ @logger.debug 'Delaying shutdown due to pending payloads', :payloads => @pending_payloads.length unless @logger.nil?
334
+
335
+ io_stop = true
336
+
337
+ # Stop spooler sending
338
+ can_send = false
339
+ @send_mutex.synchronize do
340
+ @send_ready = false
341
+ end
342
+ end
343
+ rescue TimeoutError
344
+ if @pending_payloads != 0
345
+ # Network timeout
346
+ fail TimeoutError
347
+ end
348
+
349
+ # Keepalive timeout hit, send a PING unless we were awaiting a PONG
350
+ if @pending_ping
351
+ # Timed out, break into reconnect
352
+ fail TimeoutError
353
+ end
354
+
355
+ # Stop spooler sending
356
+ can_send = false
357
+ @send_mutex.synchronize do
358
+ @send_ready = false
359
+ end
360
+
361
+ # Send PING
362
+ send_ping
363
+
364
+ @timeout = Time.now.to_i + @network_timeout
365
+ end
366
+ end
367
+ rescue ProtocolError => e
368
+ # Reconnect required due to a protocol error
369
+ @logger.warn 'Protocol error', :error => e.message unless @logger.nil?
370
+ rescue TimeoutError
371
+ # Reconnect due to timeout
372
+ @logger.warn 'Timeout occurred' unless @logger.nil?
373
+ rescue ShutdownSignal => e
374
+ raise
375
+ rescue StandardError, NativeException => e
376
+ # Unknown error occurred
377
+ @logger.warn e, :hint => 'Unknown error' unless @logger.nil?
378
+ end
379
+
380
+ def send_payload(payload)
381
+ # If we have too many pending payloads, pause the IO
382
+ if @pending_payloads.length + 1 >= @max_pending_payloads
383
+ @client.pause_send
384
+ end
385
+
386
+ # Received some events - send them
387
+ send_jdat payload
388
+
389
+ # Leave idle mode if this is the first payload after idle
390
+ if @pending_payloads.length == 1
391
+ @timeout = Time.now.to_i + @network_timeout
392
+ end
298
393
  end
299
394
 
300
395
  def generate_nonce
@@ -345,7 +440,7 @@ module LogCourier
345
440
  fail ProtocolError, "ACKN message size invalid (#{message.length})" if message.length != 20
346
441
 
347
442
  # Grab nonce
348
- nonce, sequence = message.unpack('A16N')
443
+ nonce, sequence = message.unpack('a16N')
349
444
 
350
445
  if !@logger.nil? && @logger.debug?
351
446
  nonce_str = nonce.each_byte.map do |b|
@@ -23,16 +23,15 @@ require 'thread'
23
23
 
24
24
  module LogCourier
25
25
  # TLS transport implementation
26
- class ClientTls
26
+ class ClientTcp
27
27
  def initialize(options = {})
28
28
  @options = {
29
29
  logger: nil,
30
- port: nil,
31
- addresses: [],
30
+ transport: 'tls',
32
31
  ssl_ca: nil,
33
32
  ssl_certificate: nil,
34
33
  ssl_key: nil,
35
- ssl_key_passphrase: nil
34
+ ssl_key_passphrase: nil,
36
35
  }.merge!(options)
37
36
 
38
37
  @logger = @options[:logger]
@@ -41,14 +40,13 @@ module LogCourier
41
40
  fail "output/courier: '#{k}' is required" if @options[k].nil?
42
41
  end
43
42
 
44
- fail 'output/courier: \'addresses\' must contain at least one address' if @options[:addresses].empty?
45
-
46
- c = 0
47
- [:ssl_certificate, :ssl_key].each do
48
- c += 1
43
+ if @options[:transport] == 'tls'
44
+ c = 0
45
+ [:ssl_certificate, :ssl_key].each do
46
+ c += 1
47
+ end
48
+ fail 'output/courier: \'ssl_certificate\' and \'ssl_key\' must be specified together' if c == 1
49
49
  end
50
-
51
- fail 'output/courier: \'ssl_certificate\' and \'ssl_key\' must be specified together' if c == 1
52
50
  end
53
51
 
54
52
  def connect(io_control)
@@ -67,10 +65,16 @@ module LogCourier
67
65
  @send_paused = false
68
66
 
69
67
  @send_thread = Thread.new do
70
- run_send io_control
68
+ begin
69
+ run_send io_control
70
+ rescue ShutdownSignal
71
+ end
71
72
  end
72
73
  @recv_thread = Thread.new do
73
- run_recv io_control
74
+ begin
75
+ run_recv io_control
76
+ rescue ShutdownSignal
77
+ end
74
78
  end
75
79
  return
76
80
  end
@@ -139,14 +143,18 @@ module LogCourier
139
143
  end
140
144
  end
141
145
  return
142
- rescue OpenSSL::SSL::SSLError, IOError, Errno::ECONNRESET => e
146
+ rescue OpenSSL::SSL::SSLError => e
143
147
  @logger.warn 'SSL write error', :error => e.message unless @logger.nil?
144
148
  io_control << ['F']
145
149
  return
146
- rescue ShutdownSignal
150
+ rescue IOError, Errno::ECONNRESET => e
151
+ @logger.warn 'Write error', :error => e.message unless @logger.nil?
152
+ io_control << ['F']
147
153
  return
154
+ rescue ShutdownSignal
155
+ raise
148
156
  rescue StandardError, NativeException => e
149
- @logger.warn e, :hint => 'Unknown SSL write error' unless @logger.nil?
157
+ @logger.warn e, :hint => 'Unknown write error' unless @logger.nil?
150
158
  io_control << ['F']
151
159
  return
152
160
  end
@@ -174,18 +182,22 @@ module LogCourier
174
182
  io_control << ['R', signature, message]
175
183
  end
176
184
  return
177
- rescue OpenSSL::SSL::SSLError, IOError, Errno::ECONNRESET => e
185
+ rescue OpenSSL::SSL::SSLError => e
178
186
  @logger.warn 'SSL read error', :error => e.message unless @logger.nil?
179
187
  io_control << ['F']
180
188
  return
189
+ rescue IOError, Errno::ECONNRESET => e
190
+ @logger.warn 'Read error', :error => e.message unless @logger.nil?
191
+ io_control << ['F']
192
+ return
181
193
  rescue EOFError
182
194
  @logger.warn 'Connection closed by server' unless @logger.nil?
183
195
  io_control << ['F']
184
196
  return
185
197
  rescue ShutdownSignal
186
- return
187
- rescue => e
188
- @logger.warn e, :hint => 'Unknown SSL read error' unless @logger.nil?
198
+ raise
199
+ rescue StandardError, NativeException => e
200
+ @logger.warn e, :hint => 'Unknown read error' unless @logger.nil?
189
201
  io_control << ['F']
190
202
  return
191
203
  end
@@ -200,24 +212,37 @@ module LogCourier
200
212
  begin
201
213
  tcp_socket = TCPSocket.new(address, port)
202
214
 
203
- ssl = OpenSSL::SSL::SSLContext.new
204
-
205
- unless @options[:ssl_certificate].nil?
206
- ssl.cert = OpenSSL::X509::Certificate.new(File.read(@options[:ssl_certificate]))
207
- ssl.key = OpenSSL::PKey::RSA.new(File.read(@options[:ssl_key]), @options[:ssl_key_passphrase])
208
- end
215
+ if @options[:transport] == 'tls'
216
+ ssl = OpenSSL::SSL::SSLContext.new
217
+
218
+ # Disable SSLv2 and SSLv3
219
+ # Call set_params first to ensure options attribute is there (hmmmm?)
220
+ ssl.set_params
221
+ # Modify the default options to ensure SSLv2 and SSLv3 is disabled
222
+ # This retains any beneficial options set by default in the current Ruby implementation
223
+ ssl.options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
224
+ ssl.options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
225
+
226
+ # Set the certificate file
227
+ unless @options[:ssl_certificate].nil?
228
+ ssl.cert = OpenSSL::X509::Certificate.new(File.read(@options[:ssl_certificate]))
229
+ ssl.key = OpenSSL::PKey::RSA.new(File.read(@options[:ssl_key]), @options[:ssl_key_passphrase])
230
+ end
209
231
 
210
- cert_store = OpenSSL::X509::Store.new
211
- cert_store.add_file(@options[:ssl_ca])
212
- ssl.cert_store = cert_store
213
- ssl.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
232
+ cert_store = OpenSSL::X509::Store.new
233
+ cert_store.add_file(@options[:ssl_ca])
234
+ ssl.cert_store = cert_store
235
+ ssl.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
214
236
 
215
- @ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_socket)
237
+ @ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_socket)
216
238
 
217
- socket = @ssl_client.connect
239
+ socket = @ssl_client.connect
218
240
 
219
- # Verify certificate
220
- socket.post_connection_check(address)
241
+ # Verify certificate
242
+ socket.post_connection_check(address)
243
+ else
244
+ socket = tcp_socket.connect
245
+ end
221
246
 
222
247
  # Add extra logging data now we're connected
223
248
  @logger['address'] = address
@@ -135,14 +135,18 @@ module LogCourier
135
135
  # Returns +true+ if the queue is empty.
136
136
  #
137
137
  def empty?
138
- @que.empty?
138
+ @mutex.synchronize do
139
+ return @que.empty?
140
+ end
139
141
  end
140
142
 
141
143
  #
142
144
  # Removes all objects from the queue.
143
145
  #
144
146
  def clear
145
- @que.clear
147
+ @mutex.synchronize do
148
+ @que.clear
149
+ end
146
150
  self
147
151
  end
148
152
 
@@ -150,7 +154,9 @@ module LogCourier
150
154
  # Returns the length of the queue.
151
155
  #
152
156
  def length
153
- @que.length
157
+ @mutex.synchronize do
158
+ return @que.length
159
+ end
154
160
  end
155
161
 
156
162
  #
@@ -162,7 +168,9 @@ module LogCourier
162
168
  # Returns the number of threads waiting on the queue.
163
169
  #
164
170
  def num_waiting
165
- @num_waiting + @num_enqueue_waiting
171
+ @mutex.synchronize do
172
+ return @num_waiting + @num_enqueue_waiting
173
+ end
166
174
  end
167
175
 
168
176
  private
@@ -36,11 +36,11 @@ module LogCourier
36
36
  def initialize(options = {})
37
37
  @options = {
38
38
  logger: nil,
39
- transport: 'tls'
39
+ transport: 'tls',
40
40
  }.merge!(options)
41
41
 
42
42
  @logger = @options[:logger]
43
- @logger['plugin'] = 'input/courier'
43
+ @logger['plugin'] = 'input/courier' unless @logger.nil?
44
44
 
45
45
  case @options[:transport]
46
46
  when 'tcp', 'tls'
@@ -59,7 +59,7 @@ module LogCourier
59
59
 
60
60
  # Load the json adapter
61
61
  @json_adapter = MultiJson.adapter.instance
62
- @json_options = { raw: true, use_bigdecimal: true }
62
+ @json_options = { raw: true }
63
63
  end
64
64
 
65
65
  def run(&block)
@@ -191,7 +191,7 @@ module LogCourier
191
191
  # Full pipeline, partial ack
192
192
  # NOTE: comm.send can raise a Timeout::Error of its own
193
193
  @logger.debug 'Partially acknowledging message', :nonce => nonce_str.join, :sequence => sequence if !@logger.nil? && @logger.debug?
194
- comm.send 'ACKN', [nonce, sequence].pack('A*N')
194
+ comm.send 'ACKN', [nonce, sequence].pack('a*N')
195
195
  ack_timeout = Time.now.to_i + 5
196
196
  retry
197
197
  end
@@ -87,6 +87,16 @@ module LogCourier
87
87
 
88
88
  if @options[:transport] == 'tls'
89
89
  ssl = OpenSSL::SSL::SSLContext.new
90
+
91
+ # Disable SSLv2 and SSLv3
92
+ # Call set_params first to ensure options attribute is there (hmmmm?)
93
+ ssl.set_params
94
+ # Modify the default options to ensure SSLv2 and SSLv3 is disabled
95
+ # This retains any beneficial options set by default in the current Ruby implementation
96
+ ssl.options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
97
+ ssl.options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
98
+
99
+ # Set the certificate file
90
100
  ssl.cert = OpenSSL::X509::Certificate.new(File.read(@options[:ssl_certificate]))
91
101
  ssl.key = OpenSSL::PKey::RSA.new(File.read(@options[:ssl_key]), @options[:ssl_key_passphrase])
92
102
 
@@ -134,7 +144,7 @@ module LogCourier
134
144
  client = @server.accept
135
145
  rescue EOFError, OpenSSL::SSL::SSLError, IOError => e
136
146
  # Accept failure or other issue
137
- @logger.warn 'Connection failed to accept', :error => e.message, :peer => @tcp_server.peer unless @logger.nil
147
+ @logger.warn 'Connection failed to accept', :error => e.message, :peer => @tcp_server.peer unless @logger.nil?
138
148
  client.close rescue nil unless client.nil?
139
149
  next
140
150
  end
@@ -254,10 +264,14 @@ module LogCourier
254
264
  @logger.info 'Connection closed', :peer => @peer unless @logger.nil?
255
265
  end
256
266
  return
257
- rescue OpenSSL::SSL::SSLError, IOError, Errno::ECONNRESET => e
267
+ rescue OpenSSL::SSL::SSLError => e
258
268
  # Read errors, only action is to shutdown which we'll do in ensure
259
269
  @logger.warn 'SSL error, connection aborted', :error => e.message, :peer => @peer unless @logger.nil?
260
270
  return
271
+ rescue IOError, Errno::ECONNRESET => e
272
+ # Read errors, only action is to shutdown which we'll do in ensure
273
+ @logger.warn 'Connection aborted', :error => e.message, :peer => @peer unless @logger.nil?
274
+ return
261
275
  rescue ProtocolError => e
262
276
  # Connection abort request due to a protocol error
263
277
  @logger.warn 'Protocol error, connection aborted', :error => e.message, :peer => @peer unless @logger.nil?
@@ -85,7 +85,7 @@ module LogCourier
85
85
 
86
86
  bind = 'tcp://' + @options[:address] + (@options[:port] == 0 ? ':*' : ':' + @options[:port].to_s)
87
87
  rc = @socket.bind(bind)
88
- fail 'failed to bind at ' + bind + ': ' + rZMQ::Util.error_string unless ZMQ::Util.resultcode_ok?(rc)
88
+ fail 'failed to bind at ' + bind + ': ' + ZMQ::Util.error_string unless ZMQ::Util.resultcode_ok?(rc)
89
89
 
90
90
  # Lookup port number that was allocated in case it was set to 0
91
91
  endpoint = ''
@@ -273,8 +273,12 @@ module LogCourier
273
273
  }
274
274
  end
275
275
 
276
- # Existing thread, throw on the queue, if not enough room drop the message
277
- index['']['client'].push data, 0
276
+ # Existing thread, throw on the queue, if not enough room (timeout) drop the message
277
+ begin
278
+ index['']['client'].push data, 0
279
+ rescue LogCourier::TimeoutError
280
+ # TODO: Log a warning about this?
281
+ end
278
282
  end
279
283
  return
280
284
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: log-courier
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.3'
4
+ version: 1.6.pre.40.g3efb33c
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Woods
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-02 00:00:00.000000000 Z
11
+ date: 2015-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cabin
@@ -60,7 +60,7 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - lib/log-courier/client.rb
63
- - lib/log-courier/client_tls.rb
63
+ - lib/log-courier/client_tcp.rb
64
64
  - lib/log-courier/event_queue.rb
65
65
  - lib/log-courier/server.rb
66
66
  - lib/log-courier/server_tcp.rb
@@ -81,9 +81,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
81
  version: '0'
82
82
  required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  requirements:
84
- - - '>='
84
+ - - '>'
85
85
  - !ruby/object:Gem::Version
86
- version: '0'
86
+ version: 1.3.1
87
87
  requirements: []
88
88
  rubyforge_project: nowarning
89
89
  rubygems_version: 2.4.2