jls-lumberjack 0.0.20 → 0.0.21

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: 257e7277d9d370246671e1a117e9102674386177
4
- data.tar.gz: be48c31b83ccecc610c152a1c928f8040dd3a1dd
3
+ metadata.gz: 9a5fbaaf0c05070435f5ce9299ef8b4d67309f0a
4
+ data.tar.gz: 8b382ea94f4dc405580cad2477c3209a59c6b95e
5
5
  SHA512:
6
- metadata.gz: 998a1720267a70608f3061a661624d420875e66bef41eba4193047815319023da6de7365d0b934ee1983f96c4ee8e28e6730af77e687ab5dd5accca2294141f9
7
- data.tar.gz: 698db79fc9618f656d4767baa2bbbf058268d768744e9d38d75841acca8af4b6fcad9908221c63fff589289516ea77387822b3438346487428d932df70079874
6
+ metadata.gz: d05766693143ceb79ab82872c82acd904d9004e73fcefa769393c623d029e0731f7153522ade00709cde4b475a9a0c8d667e5a39cd51e9dc514053864cfb5ede
7
+ data.tar.gz: eca095412e36b14c8a6a71f4bf1961ddfbf849f34b1ddadbc9e283427205a1566743d047ded06bb288461d24b70471441fa6039905a75bb73df85cb6a21e23d0
@@ -4,8 +4,8 @@ require "openssl"
4
4
  require "zlib"
5
5
 
6
6
  module Lumberjack
7
-
8
- SEQUENCE_MAX = (2**(0.size * 8 -2) -1)
7
+
8
+ SEQUENCE_MAX = (2**32-1).freeze
9
9
 
10
10
  class Client
11
11
  def initialize(opts={})
@@ -73,44 +73,64 @@ module Lumberjack
73
73
  @host = @opts[:address]
74
74
  @window_size = @opts[:window_size]
75
75
 
76
- tcp_socket = TCPSocket.new(@opts[:address], @opts[:port])
77
- openssl_cert = OpenSSL::X509::Certificate.new(File.read(@opts[:ssl_certificate]))
76
+ connection_start(opts)
77
+ end
78
+
79
+ private
80
+ def connection_start(opts)
81
+ tcp_socket = TCPSocket.new(opts[:address], opts[:port])
78
82
  @socket = OpenSSL::SSL::SSLSocket.new(tcp_socket)
79
83
  @socket.connect
80
-
81
- #if @socket.peer_cert.to_s != openssl_cert.to_s
82
- # raise "Client and server certificates do not match."
83
- #end
84
-
85
84
  @socket.syswrite(["1", "W", @window_size].pack("AAN"))
86
85
  end
87
86
 
88
87
  private
89
88
  def inc
90
- @sequence = 0 if @sequence+1 > Lumberjack::SEQUENCE_MAX
91
- @sequence += 1
89
+ @sequence = 0 if @sequence + 1 > Lumberjack::SEQUENCE_MAX
90
+ @sequence = @sequence + 1
92
91
  end
93
92
 
94
93
  private
95
94
  def write(msg)
96
95
  compress = Zlib::Deflate.deflate(msg)
97
- @socket.syswrite(["1","C",compress.length,compress].pack("AANA#{compress.length}"))
96
+ payload = ["1","C",compress.length,compress].pack("AANA#{compress.length}")
97
+ # SSLSocket has a limit of 16k per message
98
+ # execute multiple writes if needed
99
+ bytes_written = 0
100
+ while bytes_written < payload.bytesize
101
+ bytes_written += @socket.syswrite(payload.byteslice(bytes_written..-1))
102
+ end
98
103
  end
99
104
 
100
105
  public
101
106
  def write_hash(hash)
102
- frame = to_frame(hash, inc)
103
- ack if (@sequence - (@last_ack + 1)) >= @window_size
107
+ frame = Encoder.to_compressed_frame(hash, inc)
108
+ ack if unacked_sequence_size >= @window_size
104
109
  write frame
105
110
  end
106
111
 
107
112
  private
108
113
  def ack
109
- version = @socket.read(1)
110
- type = @socket.read(1)
114
+ _, type = read_version_and_type
111
115
  raise "Whoa we shouldn't get this frame: #{type}" if type != "A"
112
- @last_ack = @socket.read(4).unpack("N").first
113
- ack if (@sequence - (@last_ack + 1)) >= @window_size
116
+ @last_ack = read_last_ack
117
+ ack if unacked_sequence_size >= @window_size
118
+ end
119
+
120
+ private
121
+ def unacked_sequence_size
122
+ sequence - (@last_ack + 1)
123
+ end
124
+
125
+ private
126
+ def read_version_and_type
127
+ version = @socket.read(1)
128
+ type = @socket.read(1)
129
+ [version, type]
130
+ end
131
+ private
132
+ def read_last_ack
133
+ @socket.read(4).unpack("N").first
114
134
  end
115
135
 
116
136
  private
@@ -122,8 +142,8 @@ module Lumberjack
122
142
  pack << "N"
123
143
  keys.each do |k|
124
144
  val = deep_get(hash,k)
125
- key_length = k.length
126
- val_length = val.length
145
+ key_length = k.bytesize
146
+ val_length = val.bytesize
127
147
  frame << key_length
128
148
  pack << "N"
129
149
  frame << k
@@ -155,4 +175,51 @@ module Lumberjack
155
175
  keys.flatten
156
176
  end
157
177
  end
178
+
179
+ module Encoder
180
+ def self.to_compressed_frame(hash, sequence)
181
+ compress = Zlib::Deflate.deflate(to_frame(hash, sequence))
182
+ ["1", "C", compress.bytesize, compress].pack("AANA#{compress.length}")
183
+ end
184
+
185
+ def self.to_frame(hash, sequence)
186
+ frame = ["1", "D", sequence]
187
+ pack = "AAN"
188
+ keys = deep_keys(hash)
189
+ frame << keys.length
190
+ pack << "N"
191
+ keys.each do |k|
192
+ val = deep_get(hash,k)
193
+ key_length = k.bytesize
194
+ val_length = val.bytesize
195
+ frame << key_length
196
+ pack << "N"
197
+ frame << k
198
+ pack << "A#{key_length}"
199
+ frame << val_length
200
+ pack << "N"
201
+ frame << val
202
+ pack << "A#{val_length}"
203
+ end
204
+ frame.pack(pack)
205
+ end
206
+
207
+ private
208
+ def self.deep_get(hash, key="")
209
+ return hash if key.nil?
210
+ deep_get(
211
+ hash[key.split('.').first],
212
+ key[key.split('.').first.length+1..key.length]
213
+ )
214
+ end
215
+ private
216
+ def self.deep_keys(hash, prefix="")
217
+ keys = []
218
+ hash.each do |k,v|
219
+ keys << "#{prefix}#{k}" if v.class == String
220
+ keys << deep_keys(hash[k], "#{k}.") if v.class == Hash
221
+ end
222
+ keys.flatten
223
+ end
224
+ end # module Encoder
158
225
  end
@@ -22,7 +22,7 @@ module Lumberjack
22
22
  :address => "0.0.0.0",
23
23
  :ssl_certificate => nil,
24
24
  :ssl_key => nil,
25
- :ssl_key_passphrase => nil,
25
+ :ssl_key_passphrase => nil
26
26
  }.merge(options)
27
27
 
28
28
  [:ssl_certificate, :ssl_key].each do |k|
@@ -31,7 +31,8 @@ module Lumberjack
31
31
  end
32
32
  end
33
33
 
34
- @tcp_server = TCPServer.new(@options[:port])
34
+ @tcp_server = TCPServer.new(@options[:address], @options[:port])
35
+
35
36
  # Query the port in case the port number is '0'
36
37
  # TCPServer#addr == [ address_family, port, address, address ]
37
38
  @port = @tcp_server.addr[1]
@@ -44,22 +45,26 @@ module Lumberjack
44
45
 
45
46
  def run(&block)
46
47
  while true
47
- # NOTE: This means ssl accepting is single-threaded.
48
- begin
49
- client = @ssl_server.accept
50
- rescue EOFError, OpenSSL::SSL::SSLError, IOError
51
- # ssl handshake failure or other issue, skip it.
52
- # TODO(sissel): log the error
53
- # TODO(sissel): try to identify what client was connecting that failed.
54
- client.close rescue nil
55
- next
56
- end
57
-
58
- Thread.new(client) do |fd|
59
- Connection.new(fd).run(&block)
48
+ connection = accept
49
+ Thread.new(connection) do |connection|
50
+ connection.run(&block)
60
51
  end
61
52
  end
62
53
  end # def run
54
+
55
+ def accept(&block)
56
+ begin
57
+ fd = @ssl_server.accept
58
+ rescue EOFError, OpenSSL::SSL::SSLError, IOError
59
+ # ssl handshake or other accept-related failure.
60
+ # TODO(sissel): Make it possible to log this.
61
+ end
62
+ if block_given?
63
+ block.call(fd)
64
+ else
65
+ Connection.new(fd)
66
+ end
67
+ end
63
68
  end # class Server
64
69
 
65
70
  class Parser
@@ -92,16 +97,16 @@ module Lumberjack
92
97
  while have?(@need)
93
98
  send(@state, &block)
94
99
  #case @state
95
- #when :header; header(&block)
96
- #when :window_size; window_size(&block)
97
- #when :data_lead; data_lead(&block)
98
- #when :data_field_key_len; data_field_key_len(&block)
99
- #when :data_field_key; data_field_key(&block)
100
- #when :data_field_value_len; data_field_value_len(&block)
101
- #when :data_field_value; data_field_value(&block)
102
- #when :data_field_value; data_field_value(&block)
103
- #when :compressed_lead; compressed_lead(&block)
104
- #when :compressed_payload; compressed_payload(&block)
100
+ #when :header; header(&block)
101
+ #when :window_size; window_size(&block)
102
+ #when :data_lead; data_lead(&block)
103
+ #when :data_field_key_len; data_field_key_len(&block)
104
+ #when :data_field_key; data_field_key(&block)
105
+ #when :data_field_value_len; data_field_value_len(&block)
106
+ #when :data_field_value; data_field_value(&block)
107
+ #when :data_field_value; data_field_value(&block)
108
+ #when :compressed_lead; compressed_lead(&block)
109
+ #when :compressed_payload; compressed_payload(&block)
105
110
  #end # case @state
106
111
  end
107
112
  return nil
@@ -136,10 +141,10 @@ module Lumberjack
136
141
  version, frame_type = get.bytes.to_a[0..1]
137
142
 
138
143
  case frame_type
139
- when FRAME_WINDOW; transition(:window_size, 4)
140
- when FRAME_DATA; transition(:data_lead, 8)
141
- when FRAME_COMPRESSED; transition(:compressed_lead, 4)
142
- else; raise "Unknown frame type: #{frame_type}"
144
+ when FRAME_WINDOW; transition(:window_size, 4)
145
+ when FRAME_DATA; transition(:data_lead, 8)
146
+ when FRAME_COMPRESSED; transition(:compressed_lead, 4)
147
+ else; raise "Unknown frame type: #{frame_type}"
143
148
  end
144
149
  end
145
150
 
@@ -189,7 +194,7 @@ module Lumberjack
189
194
  length = get.unpack("N").first
190
195
  transition(:compressed_payload, length)
191
196
  end
192
-
197
+
193
198
  def compressed_payload(&block)
194
199
  original = Zlib::Inflate.inflate(get)
195
200
  transition(:header, 2)
@@ -219,8 +224,8 @@ module Lumberjack
219
224
  # X: too many events after errors.
220
225
  @parser.feed(@fd.sysread(16384)) do |event, *args|
221
226
  case event
222
- when :window_size; window_size(*args, &block)
223
- when :data; data(*args, &block)
227
+ when :window_size; window_size(*args, &block)
228
+ when :data; data(*args, &block)
224
229
  end
225
230
  #send(event, *args)
226
231
  end # feed
@@ -229,16 +234,19 @@ module Lumberjack
229
234
  # EOF or other read errors, only action is to shutdown which we'll do in
230
235
  # 'ensure'
231
236
  ensure
232
- # Try to ensure it's closed, but if this fails I don't care.
233
- @fd.close rescue nil
237
+ close rescue 'Already closed stream'
234
238
  end # def run
235
239
 
240
+ def close
241
+ @fd.close
242
+ end
243
+
236
244
  def window_size(size)
237
245
  @window_size = size
238
246
  end
239
247
 
240
248
  def data(sequence, map, &block)
241
- block.call(map)
249
+ block.call(map) if block_given?
242
250
  if (sequence - @last_ack) >= @window_size
243
251
  @fd.syswrite(["1A", sequence].pack("A*N"))
244
252
  @last_ack = sequence
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jls-lumberjack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Sissel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-12 00:00:00.000000000 Z
11
+ date: 2015-02-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: lumberjack log transport library
14
14
  email:
@@ -17,11 +17,10 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - lib/lumberjack/server.rb
21
20
  - lib/lumberjack/client.rb
21
+ - lib/lumberjack/server.rb
22
22
  homepage: https://github.com/jordansissel/lumberjack
23
- licenses:
24
- - Apache 2.0
23
+ licenses: []
25
24
  metadata: {}
26
25
  post_install_message:
27
26
  rdoc_options: []
@@ -29,17 +28,17 @@ require_paths:
29
28
  - lib
30
29
  required_ruby_version: !ruby/object:Gem::Requirement
31
30
  requirements:
32
- - - '>='
31
+ - - ">="
33
32
  - !ruby/object:Gem::Version
34
33
  version: '0'
35
34
  required_rubygems_version: !ruby/object:Gem::Requirement
36
35
  requirements:
37
- - - '>='
36
+ - - ">="
38
37
  - !ruby/object:Gem::Version
39
38
  version: '0'
40
39
  requirements: []
41
40
  rubyforge_project:
42
- rubygems_version: 2.1.11
41
+ rubygems_version: 2.4.3
43
42
  signing_key:
44
43
  specification_version: 4
45
44
  summary: lumberjack log transport library