thrift_client-adamd 0.9.3
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 +15 -0
- data/lib/thrift_client/abstract_thrift_client.rb +226 -0
- data/lib/thrift_client/connection/base.rb +25 -0
- data/lib/thrift_client/connection/factory.rb +13 -0
- data/lib/thrift_client/connection/http.rb +29 -0
- data/lib/thrift_client/connection/socket.rb +29 -0
- data/lib/thrift_client/connection.rb +4 -0
- data/lib/thrift_client/event_machine.rb +145 -0
- data/lib/thrift_client/server.rb +108 -0
- data/lib/thrift_client/simple.rb +272 -0
- data/lib/thrift_client/thrift.rb +40 -0
- data/lib/thrift_client.rb +34 -0
- data/test/greeter/greeter.rb +121 -0
- data/test/greeter/server.rb +44 -0
- data/test/multiple_working_servers_test.rb +112 -0
- data/test/simple_test.rb +136 -0
- data/test/test_helper.rb +12 -0
- data/test/thrift_client_http_test.rb +45 -0
- data/test/thrift_client_test.rb +289 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OWViNmI3NWQ1NjRmYzZiMmY2MzliMTY5Y2EzNWUwZDY2MTJlYTQ2ZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTZiNzZmOWRmYjI3OTVjYmRmMmU4YWI3NTdiNjNiZTFiZWEzZTFlNQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
M2YxNjg2YzFhNWQ0MWYxNTFmMjNhOWUyOTQzNjliMDZmMWQyYmI2YjVkMzY3
|
10
|
+
MWRkZDRmMmIxZjM5NzYxOWYwMzE5ZWZjNTExYmFkNzVhMzZjNjdmYjBkMjk3
|
11
|
+
ZWQ2M2Q4YzlkMWVhMjkxNzgyNzY1NWRkZTYwOTJjMTExMTE0MWM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OWViYThkYWRjOWJkNzBlZWJiOWM3NGJlMjc5ZjE4MThmNGE1ZGQ4ODNlYTA4
|
14
|
+
Y2QxYWYyM2E1MGNjOTUwZDU4NTRkOThkY2I4MTMzMTE5Y2FkZWRjN2JlNzA1
|
15
|
+
ZDQ0YjAyYmUyZTJjY2NmNmZiZTY1NzQ4Zjg0NmQ4YmI3OGExOTU=
|
@@ -0,0 +1,226 @@
|
|
1
|
+
class AbstractThriftClient
|
2
|
+
include ThriftHelpers
|
3
|
+
|
4
|
+
DISCONNECT_ERRORS = [
|
5
|
+
IOError,
|
6
|
+
Thrift::Exception,
|
7
|
+
Thrift::ApplicationException,
|
8
|
+
Thrift::TransportException
|
9
|
+
]
|
10
|
+
|
11
|
+
DEFAULT_WRAPPED_ERRORS = [
|
12
|
+
Thrift::ApplicationException,
|
13
|
+
Thrift::TransportException,
|
14
|
+
]
|
15
|
+
|
16
|
+
DEFAULTS = {
|
17
|
+
:protocol => Thrift::BinaryProtocol,
|
18
|
+
:protocol_extra_params => [],
|
19
|
+
:transport => Thrift::Socket,
|
20
|
+
:transport_wrapper => Thrift::FramedTransport,
|
21
|
+
:raise => true,
|
22
|
+
:defaults => {},
|
23
|
+
:exception_classes => DISCONNECT_ERRORS,
|
24
|
+
:exception_class_overrides => [],
|
25
|
+
:retries => 0,
|
26
|
+
:server_retry_period => 1,
|
27
|
+
:server_max_requests => nil,
|
28
|
+
:retry_overrides => {},
|
29
|
+
:wrapped_exception_classes => DEFAULT_WRAPPED_ERRORS,
|
30
|
+
:connect_timeout => 0.1,
|
31
|
+
:timeout => 1,
|
32
|
+
:timeout_overrides => {},
|
33
|
+
:cached_connections => false
|
34
|
+
}
|
35
|
+
|
36
|
+
attr_reader :last_client, :client, :client_class, :current_server, :server_list, :options, :client_methods
|
37
|
+
|
38
|
+
def self.create_wrapped_exception_classes(client_class, wrapped_exception_classes = DEFAULT_WRAPPED_ERRORS)
|
39
|
+
wrapped_exception_classes.map do |exception_klass|
|
40
|
+
name = exception_klass.to_s.split('::').last
|
41
|
+
begin
|
42
|
+
client_class.const_get(name)
|
43
|
+
rescue NameError
|
44
|
+
client_class.const_set(name, Class.new(exception_klass))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(client_class, servers, options = {})
|
50
|
+
@options = DEFAULTS.merge(options)
|
51
|
+
@options[:server_retry_period] ||= 0
|
52
|
+
|
53
|
+
@client_class = client_class
|
54
|
+
@server_list = Array(servers).collect do |s|
|
55
|
+
Server.new(s, @client_class, @options)
|
56
|
+
end.sort_by { rand }
|
57
|
+
|
58
|
+
@current_server = @server_list.first
|
59
|
+
|
60
|
+
@callbacks = {}
|
61
|
+
@client_methods = []
|
62
|
+
@client_class.instance_methods.each do |method_name|
|
63
|
+
if method_name != 'send_message' && method_name =~ /^send_(.*)$/
|
64
|
+
instance_eval("def #{$1}(*args); handled_proxy(:'#{$1}', *args); end", __FILE__, __LINE__)
|
65
|
+
@client_methods << $1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@request_count = 0
|
69
|
+
self.class.create_wrapped_exception_classes(@client_class, @options[:wrapped_exception_classes])
|
70
|
+
end
|
71
|
+
|
72
|
+
# Adds a callback that will be invoked at a certain time. The valid callback types are:
|
73
|
+
# :post_connect - should accept a single AbstractThriftClient argument, which is the client object to
|
74
|
+
# which the callback was added. Called after a connection to the remote thrift server
|
75
|
+
# is established.
|
76
|
+
# :before_method - should accept a single method name argument. Called before a method is invoked on the
|
77
|
+
# thrift server.
|
78
|
+
# :on_exception - should accept 2 args: an Exception instance and a method name. Called right before the
|
79
|
+
# exception is raised.
|
80
|
+
def add_callback(callback_type, &block)
|
81
|
+
case callback_type
|
82
|
+
when :post_connect, :before_method, :on_exception
|
83
|
+
@callbacks[callback_type] ||= []
|
84
|
+
@callbacks[callback_type].push(block)
|
85
|
+
# Allow chaining
|
86
|
+
return self
|
87
|
+
else
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def inspect
|
93
|
+
"<#{self.class}(#{client_class}) @current_server=#{@current_server}>"
|
94
|
+
end
|
95
|
+
|
96
|
+
# Force the client to connect to the server. Not necessary to be
|
97
|
+
# called as the connection will be made on the first RPC method
|
98
|
+
# call.
|
99
|
+
def connect!(method = nil)
|
100
|
+
start_time ||= Time.now
|
101
|
+
@current_server = next_live_server
|
102
|
+
@client = @current_server.client
|
103
|
+
@last_client = @client
|
104
|
+
do_callbacks(:post_connect, self)
|
105
|
+
rescue IOError, Thrift::TransportException
|
106
|
+
disconnect!(true)
|
107
|
+
timeout = timeout(method)
|
108
|
+
if timeout && Time.now - start_time > timeout
|
109
|
+
no_servers_available!
|
110
|
+
else
|
111
|
+
retry
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def disconnect!(error = false)
|
116
|
+
if @current_server
|
117
|
+
@current_server.mark_down!(@options[:server_retry_period]) if error
|
118
|
+
@current_server.close
|
119
|
+
end
|
120
|
+
|
121
|
+
@client = nil
|
122
|
+
@current_server = nil
|
123
|
+
@request_count = 0
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# Calls all callbacks of the specified type with the given args
|
129
|
+
def do_callbacks(callback_type_sym, *args)
|
130
|
+
return unless @callbacks[callback_type_sym]
|
131
|
+
@callbacks[callback_type_sym].each do |callback|
|
132
|
+
callback.call(*args)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def next_live_server
|
137
|
+
@server_index ||= 0
|
138
|
+
@server_list.length.times do |i|
|
139
|
+
cur = (1 + @server_index + i) % @server_list.length
|
140
|
+
if @server_list[cur].up?
|
141
|
+
@server_index = cur
|
142
|
+
return @server_list[cur]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
no_servers_available!
|
146
|
+
end
|
147
|
+
|
148
|
+
def ensure_socket_alignment
|
149
|
+
incomplete = true
|
150
|
+
result = yield
|
151
|
+
incomplete = false
|
152
|
+
result
|
153
|
+
# Thrift exceptions get read off the wire. We can consider them complete requests
|
154
|
+
rescue Thrift::Exception => e
|
155
|
+
incomplete = false
|
156
|
+
raise e
|
157
|
+
ensure
|
158
|
+
disconnect! if incomplete
|
159
|
+
end
|
160
|
+
|
161
|
+
def handled_proxy(method_name, *args)
|
162
|
+
begin
|
163
|
+
connect!(method_name.to_sym) unless @client
|
164
|
+
if has_timeouts?
|
165
|
+
@client.timeout = timeout(method_name.to_sym)
|
166
|
+
end
|
167
|
+
@request_count += 1
|
168
|
+
do_callbacks(:before_method, method_name)
|
169
|
+
ensure_socket_alignment { @client.send(method_name, *args) }
|
170
|
+
rescue *@options[:exception_class_overrides] => e
|
171
|
+
raise_or_default(e, method_name)
|
172
|
+
rescue *@options[:exception_classes] => e
|
173
|
+
disconnect!(true)
|
174
|
+
tries ||= (@options[:retry_overrides][method_name.to_sym] || @options[:retries]) + 1
|
175
|
+
tries -= 1
|
176
|
+
if tries > 0
|
177
|
+
retry
|
178
|
+
else
|
179
|
+
raise_or_default(e, method_name)
|
180
|
+
end
|
181
|
+
rescue Exception => e
|
182
|
+
raise_or_default(e, method_name)
|
183
|
+
ensure
|
184
|
+
disconnect! if @options[:server_max_requests] && @request_count >= @options[:server_max_requests]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def raise_or_default(e, method_name)
|
189
|
+
if @options[:raise]
|
190
|
+
raise_wrapped_error(e, method_name)
|
191
|
+
else
|
192
|
+
@options[:defaults][method_name.to_sym]
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def raise_wrapped_error(e, method_name)
|
197
|
+
do_callbacks(:on_exception, e, method_name)
|
198
|
+
if @options[:wrapped_exception_classes].include?(e.class)
|
199
|
+
raise @client_class.const_get(e.class.to_s.split('::').last), e.message, e.backtrace
|
200
|
+
else
|
201
|
+
raise e
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def has_timeouts?
|
206
|
+
@has_timeouts ||= @options[:timeout_overrides].any? && transport_can_timeout?
|
207
|
+
end
|
208
|
+
|
209
|
+
def timeout(method = nil)
|
210
|
+
@options[:timeout_overrides][method] || @options[:timeout]
|
211
|
+
end
|
212
|
+
|
213
|
+
def transport_can_timeout?
|
214
|
+
if (@options[:transport_wrapper] || @options[:transport]).method_defined?(:timeout=)
|
215
|
+
true
|
216
|
+
else
|
217
|
+
warn "ThriftClient: Timeout overrides have no effect with with transport type #{(@options[:transport_wrapper] || @options[:transport])}"
|
218
|
+
false
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def no_servers_available!
|
223
|
+
servers = @server_list.map { |s| s.to_s }.join(',')
|
224
|
+
raise ThriftClient::NoServersAvailable, "No live servers in [#{servers}]."
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ThriftHelpers
|
2
|
+
module Connection
|
3
|
+
class Base
|
4
|
+
attr_accessor :transport, :server
|
5
|
+
|
6
|
+
def initialize(transport, transport_wrapper, server, timeout)
|
7
|
+
@transport = transport
|
8
|
+
@transport_wrapper = transport_wrapper
|
9
|
+
@server = server
|
10
|
+
@timeout = timeout
|
11
|
+
end
|
12
|
+
|
13
|
+
def connect!
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def open?
|
18
|
+
@transport.open?
|
19
|
+
end
|
20
|
+
|
21
|
+
def close
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ThriftHelpers
|
2
|
+
module Connection
|
3
|
+
class Factory
|
4
|
+
def self.create(transport, transport_wrapper, server, timeout)
|
5
|
+
if transport == Thrift::HTTPClientTransport
|
6
|
+
Connection::HTTP.new(transport, transport_wrapper, server, timeout)
|
7
|
+
else
|
8
|
+
Connection::Socket.new(transport, transport_wrapper, server, timeout)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ThriftHelpers
|
2
|
+
module Connection
|
3
|
+
class HTTP < Base
|
4
|
+
def initialize(*args)
|
5
|
+
super *args
|
6
|
+
|
7
|
+
uri = parse_server(@server)
|
8
|
+
@transport = Thrift::HTTPClientTransport.new(@server)
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect!
|
12
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
13
|
+
http.use_ssl = uri.scheme == "https"
|
14
|
+
http.get(uri.path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def open?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def parse_server(server)
|
23
|
+
uri = URI.parse(server)
|
24
|
+
raise ArgumentError, 'Servers must start with http' unless uri.scheme =~ /^http/
|
25
|
+
uri
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ThriftHelpers
|
2
|
+
module Connection
|
3
|
+
class Socket < Base
|
4
|
+
def initialize(*args)
|
5
|
+
super *args
|
6
|
+
|
7
|
+
host, port = parse_server(@server)
|
8
|
+
@transport = @transport.new(host, port.to_i, @timeout)
|
9
|
+
@transport = @transport_wrapper.new(@transport) if @transport_wrapper
|
10
|
+
end
|
11
|
+
|
12
|
+
def close
|
13
|
+
@transport.close
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect!
|
17
|
+
@transport.open
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_server(server)
|
23
|
+
host, port = server.to_s.split(":")
|
24
|
+
raise ArgumentError, 'Servers must be in the form "host:port"' unless host and port
|
25
|
+
[host, port]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
raise RuntimeError, "The eventmachine transport requires Ruby 1.9.x" if RUBY_VERSION < '1.9.0'
|
2
|
+
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'fiber'
|
5
|
+
|
6
|
+
# EventMachine-ready Thrift connection
|
7
|
+
# Should not be used with a transport wrapper since it already performs buffering in Ruby.
|
8
|
+
module Thrift
|
9
|
+
class EventMachineTransport < BaseTransport
|
10
|
+
def initialize(host, port=9090, timeout=5)
|
11
|
+
@host, @port, @timeout = host, port, timeout
|
12
|
+
@connection = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def open?
|
16
|
+
@connection && @connection.connected?
|
17
|
+
end
|
18
|
+
|
19
|
+
def open
|
20
|
+
fiber = Fiber.current
|
21
|
+
@connection = EventMachineConnection.connect(@host, @port, @timeout)
|
22
|
+
@connection.callback do
|
23
|
+
fiber.resume
|
24
|
+
end
|
25
|
+
@connection.errback do
|
26
|
+
fiber.resume
|
27
|
+
end
|
28
|
+
Fiber.yield
|
29
|
+
|
30
|
+
raise Thrift::TransportException, "Unable to connect to #{@host}:#{@port}" unless @connection.connected?
|
31
|
+
@connection
|
32
|
+
end
|
33
|
+
|
34
|
+
def close
|
35
|
+
@connection.close
|
36
|
+
end
|
37
|
+
|
38
|
+
def read(sz)
|
39
|
+
@connection.blocking_read(sz)
|
40
|
+
end
|
41
|
+
|
42
|
+
def write(buf)
|
43
|
+
@connection.send_data(buf)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module EventMachineConnection
|
48
|
+
GARBAGE_BUFFER_SIZE = 4096 # 4kB
|
49
|
+
|
50
|
+
include EM::Deferrable
|
51
|
+
|
52
|
+
def self.connect(host='localhost', port=9090, timeout=5, &block)
|
53
|
+
EM.connect(host, port, self, host, port) do |conn|
|
54
|
+
conn.pending_connect_timeout = timeout
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def trap
|
59
|
+
begin
|
60
|
+
yield
|
61
|
+
rescue Exception => ex
|
62
|
+
puts ex.message
|
63
|
+
puts ex.backtrace.join("\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def initialize(host, port=9090)
|
68
|
+
@host, @port = host, port
|
69
|
+
@index = 0
|
70
|
+
@disconnected = 'not connected'
|
71
|
+
@buf = ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def close
|
75
|
+
trap do
|
76
|
+
@disconnected = 'closed'
|
77
|
+
close_connection(true)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def blocking_read(size)
|
82
|
+
raise IOError, "lost connection to #{@host}:#{@port}: #{@disconnected}" if @disconnected
|
83
|
+
if can_read?(size)
|
84
|
+
yank(size)
|
85
|
+
else
|
86
|
+
raise ArgumentError, "Unexpected state" if @size or @callback
|
87
|
+
|
88
|
+
fiber = Fiber.current
|
89
|
+
@size = size
|
90
|
+
@callback = proc { |data|
|
91
|
+
fiber.resume(data)
|
92
|
+
}
|
93
|
+
Fiber.yield
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def receive_data(data)
|
98
|
+
trap do
|
99
|
+
(@buf) << data
|
100
|
+
|
101
|
+
if @callback and can_read?(@size)
|
102
|
+
callback = @callback
|
103
|
+
data = yank(@size)
|
104
|
+
@callback = @size = nil
|
105
|
+
callback.call(data)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def connected?
|
111
|
+
!@disconnected
|
112
|
+
end
|
113
|
+
|
114
|
+
def connection_completed
|
115
|
+
@disconnected = nil
|
116
|
+
succeed
|
117
|
+
end
|
118
|
+
|
119
|
+
def unbind
|
120
|
+
if !@disconnected
|
121
|
+
@disconnected = 'unbound'
|
122
|
+
else
|
123
|
+
fail
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def can_read?(size)
|
128
|
+
@buf.size >= @index + size
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def yank(len)
|
134
|
+
data = @buf.slice(@index, len)
|
135
|
+
@index += len
|
136
|
+
@index = @buf.size if @index > @buf.size
|
137
|
+
if @index >= GARBAGE_BUFFER_SIZE
|
138
|
+
@buf = @buf.slice(@index..-1)
|
139
|
+
@index = 0
|
140
|
+
end
|
141
|
+
data
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'thrift_client/connection'
|
2
|
+
|
3
|
+
module ThriftHelpers
|
4
|
+
class Server
|
5
|
+
class ServerMarkedDown < StandardError; end
|
6
|
+
|
7
|
+
def initialize(connection_string, client_class, options = {})
|
8
|
+
@connection_string = connection_string
|
9
|
+
@client_class = client_class
|
10
|
+
@options = options
|
11
|
+
|
12
|
+
@cached = @options.has_key?(:cached_connections) ? @options[:cached_connections] : true
|
13
|
+
|
14
|
+
@marked_down_til = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def mark_down!(til)
|
18
|
+
close(true)
|
19
|
+
@marked_down_til = Time.now + til
|
20
|
+
end
|
21
|
+
|
22
|
+
def up?
|
23
|
+
!down?
|
24
|
+
end
|
25
|
+
|
26
|
+
def down?
|
27
|
+
@marked_down_til && @marked_down_til > Time.now
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
@connection_string
|
32
|
+
end
|
33
|
+
|
34
|
+
def connection
|
35
|
+
@connection ||= Connection::Factory.create(
|
36
|
+
@options[:transport], @options[:transport_wrapper],
|
37
|
+
@connection_string, @options[:connect_timeout])
|
38
|
+
end
|
39
|
+
|
40
|
+
def connect!
|
41
|
+
return if open?
|
42
|
+
|
43
|
+
self.timeout = @options[:connect_timeout]
|
44
|
+
connection.connect!
|
45
|
+
self.timeout = @options[:timeout]
|
46
|
+
end
|
47
|
+
|
48
|
+
def client
|
49
|
+
@client ||= begin
|
50
|
+
connect!
|
51
|
+
|
52
|
+
@client_class.new(
|
53
|
+
@options[:protocol].new(self, *@options[:protocol_extra_params]))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def open?
|
58
|
+
connection.open?
|
59
|
+
end
|
60
|
+
|
61
|
+
def close(teardown = false)
|
62
|
+
if teardown || !@cached
|
63
|
+
connection.close if open?
|
64
|
+
@client = nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def transport
|
69
|
+
connection.transport
|
70
|
+
end
|
71
|
+
|
72
|
+
module TransportInterface
|
73
|
+
def read(sz)
|
74
|
+
transport.read(sz)
|
75
|
+
end
|
76
|
+
|
77
|
+
def read_byte
|
78
|
+
transport.read_byte
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_into_buffer(buffer, size)
|
82
|
+
transport.read_into_buffer(buffer, size)
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_all(sz)
|
86
|
+
transport.read_all(sz)
|
87
|
+
end
|
88
|
+
|
89
|
+
def write(buf)
|
90
|
+
transport.write(buf)
|
91
|
+
end
|
92
|
+
alias_method :<<, :write
|
93
|
+
|
94
|
+
def flush
|
95
|
+
transport.flush
|
96
|
+
end
|
97
|
+
|
98
|
+
def timeout=(timeout)
|
99
|
+
transport.timeout = timeout if transport.respond_to?(:timeout=)
|
100
|
+
end
|
101
|
+
|
102
|
+
def timeout
|
103
|
+
transport.timeout
|
104
|
+
end
|
105
|
+
end
|
106
|
+
include TransportInterface
|
107
|
+
end
|
108
|
+
end
|