jls-lumberjack 0.0.1
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.
- data/ruby/lib/lumberjack/server.rb +150 -0
- metadata +47 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require "socket"
|
|
2
|
+
require "thread"
|
|
3
|
+
require "openssl"
|
|
4
|
+
require "zlib"
|
|
5
|
+
|
|
6
|
+
module Lumberjack
|
|
7
|
+
class Server
|
|
8
|
+
attr_reader :port
|
|
9
|
+
|
|
10
|
+
# Create a new Lumberjack server.
|
|
11
|
+
#
|
|
12
|
+
# - options is a hash. Valid options are:
|
|
13
|
+
#
|
|
14
|
+
# * :port - the port to listen on
|
|
15
|
+
# * :address - the host/address to bind to
|
|
16
|
+
# * :ssl_certificate - the path to the ssl cert to use
|
|
17
|
+
# * :ssl_key - the path to the ssl key to use
|
|
18
|
+
# * :ssl_key_passphrase - the key passphrase (optional)
|
|
19
|
+
def initialize(options={})
|
|
20
|
+
@options = {
|
|
21
|
+
:port => 0,
|
|
22
|
+
:address => "0.0.0.0",
|
|
23
|
+
:ssl_certificate => nil,
|
|
24
|
+
:ssl_key => nil,
|
|
25
|
+
:ssl_key_passphrase => nil,
|
|
26
|
+
}.merge(options)
|
|
27
|
+
|
|
28
|
+
[:ssl_certificate, :ssl_key].each do |k|
|
|
29
|
+
if @options[k].nil?
|
|
30
|
+
raise "You must specify #{k} in Lumberjack::Server.new(...)"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
@tcp_server = TCPServer.new(@options[:port])
|
|
35
|
+
# Query the port in case the port number is '0'
|
|
36
|
+
# TCPServer#addr == [ address_family, port, address, address ]
|
|
37
|
+
@port = @tcp_server.addr[1]
|
|
38
|
+
@ssl = OpenSSL::SSL::SSLContext.new
|
|
39
|
+
@ssl.cert = OpenSSL::X509::Certificate.new(File.read(@options[:ssl_certificate]))
|
|
40
|
+
@ssl.key = OpenSSL::PKey::RSA.new(File.read(@options[:ssl_key]),
|
|
41
|
+
@options[:ssl_key_passphrase])
|
|
42
|
+
@ssl_server = OpenSSL::SSL::SSLServer.new(@tcp_server, @ssl)
|
|
43
|
+
end # def initialize
|
|
44
|
+
|
|
45
|
+
def run(&block)
|
|
46
|
+
while true
|
|
47
|
+
begin
|
|
48
|
+
Thread.new(@ssl_server.accept) do |fd|
|
|
49
|
+
Connection.new(fd).run(&block)
|
|
50
|
+
end
|
|
51
|
+
rescue => e
|
|
52
|
+
p :accept_error => e
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end # def run
|
|
56
|
+
end # class Server
|
|
57
|
+
|
|
58
|
+
class Connection
|
|
59
|
+
def initialize(fd)
|
|
60
|
+
@fd = fd
|
|
61
|
+
end # def initialize
|
|
62
|
+
|
|
63
|
+
def run(&block)
|
|
64
|
+
each_event(&block)
|
|
65
|
+
end # def run
|
|
66
|
+
|
|
67
|
+
def each_event(&block)
|
|
68
|
+
last_ack = 0
|
|
69
|
+
window_size = 0
|
|
70
|
+
io = IOWrap.new(@fd)
|
|
71
|
+
while true
|
|
72
|
+
version = io.read(1)
|
|
73
|
+
frame = io.read(1)
|
|
74
|
+
|
|
75
|
+
if frame == "W" # window size
|
|
76
|
+
window_size = io.read(4).unpack("N").first / 2
|
|
77
|
+
#puts "Window size: #{window_size}"
|
|
78
|
+
next
|
|
79
|
+
elsif frame == "C" # compressed data
|
|
80
|
+
length = io.read(4).unpack("N").first
|
|
81
|
+
#puts "Compressed frame length #{length}"
|
|
82
|
+
compressed = io.read(length)
|
|
83
|
+
original = Zlib::Inflate.inflate(compressed)
|
|
84
|
+
#original = LZ4::uncompress(compressed, length)
|
|
85
|
+
io.pushback(original)
|
|
86
|
+
next
|
|
87
|
+
elsif frame != "D"
|
|
88
|
+
#puts "Unexpected frame type: #{version.inspect} / #{frame.inspect}"
|
|
89
|
+
io.close
|
|
90
|
+
return
|
|
91
|
+
end
|
|
92
|
+
#
|
|
93
|
+
# data frame
|
|
94
|
+
sequence = io.read(4).unpack("N").first
|
|
95
|
+
count = io.read(4).unpack("N").first
|
|
96
|
+
|
|
97
|
+
map = {}
|
|
98
|
+
count.times do
|
|
99
|
+
key_len = io.read(4).unpack("N").first
|
|
100
|
+
key = io.read(key_len);
|
|
101
|
+
value_len = io.read(4).unpack("N").first
|
|
102
|
+
value = io.read(value_len);
|
|
103
|
+
map[key] = value
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
block.call(map)
|
|
107
|
+
|
|
108
|
+
if sequence - last_ack >= window_size
|
|
109
|
+
# ack this.
|
|
110
|
+
io.syswrite(["1", "A", sequence].pack("AAN"))
|
|
111
|
+
last_ack = sequence
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end # def each_event
|
|
115
|
+
end # class Connection
|
|
116
|
+
|
|
117
|
+
# Wrap an io-like object but support pushback.
|
|
118
|
+
class IOWrap
|
|
119
|
+
def initialize(io)
|
|
120
|
+
@io = io
|
|
121
|
+
@buffer = ""
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def read(bytes)
|
|
125
|
+
if @buffer.empty?
|
|
126
|
+
#puts "reading direct from @io"
|
|
127
|
+
return @io.read(bytes)
|
|
128
|
+
elsif @buffer.length > bytes
|
|
129
|
+
#puts "reading buffered"
|
|
130
|
+
data = @buffer[0...bytes]
|
|
131
|
+
@buffer[0...bytes] = ""
|
|
132
|
+
return data
|
|
133
|
+
else
|
|
134
|
+
data = @buffer.clone
|
|
135
|
+
@buffer.clear
|
|
136
|
+
return data + @io.read(bytes - data.length)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def pushback(data)
|
|
141
|
+
#puts "Pushback: #{data[0..30].inspect}..."
|
|
142
|
+
@buffer += data
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def method_missing(method, *args)
|
|
146
|
+
@io.send(method, *args)
|
|
147
|
+
end
|
|
148
|
+
end # class IOWrap
|
|
149
|
+
end # module Lumberjack
|
|
150
|
+
|
metadata
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jls-lumberjack
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Jordan Sissel
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-09-18 00:00:00.000000000 Z
|
|
13
|
+
dependencies: []
|
|
14
|
+
description: lumberjack log transport library
|
|
15
|
+
email:
|
|
16
|
+
- jls@semicomplete.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- ruby/lib/lumberjack/server.rb
|
|
22
|
+
homepage: https://github.com/jordansissel/lumberjack
|
|
23
|
+
licenses: []
|
|
24
|
+
post_install_message:
|
|
25
|
+
rdoc_options: []
|
|
26
|
+
require_paths:
|
|
27
|
+
- ruby/lib
|
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
+
none: false
|
|
30
|
+
requirements:
|
|
31
|
+
- - ! '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
35
|
+
none: false
|
|
36
|
+
requirements:
|
|
37
|
+
- - ! '>='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
requirements: []
|
|
41
|
+
rubyforge_project:
|
|
42
|
+
rubygems_version: 1.8.24
|
|
43
|
+
signing_key:
|
|
44
|
+
specification_version: 3
|
|
45
|
+
summary: lumberjack log transport library
|
|
46
|
+
test_files: []
|
|
47
|
+
has_rdoc:
|