thrift 0.23.0 → 0.25.0
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 +4 -4
- data/README.md +203 -40
- data/ext/binary_protocol_accelerated.c +130 -40
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +184 -91
- data/ext/constants.h +3 -0
- data/ext/extconf.rb +12 -4
- data/ext/macros.h +11 -0
- data/ext/memory_buffer.c +67 -12
- data/ext/struct.c +192 -71
- data/ext/thrift_native.c +7 -0
- data/lib/thrift/bytes.rb +6 -3
- data/lib/thrift/client.rb +31 -33
- data/lib/thrift/exceptions.rb +11 -8
- data/lib/thrift/multiplexed_processor.rb +17 -8
- data/lib/thrift/processor.rb +25 -3
- data/lib/thrift/protocol/base_protocol.rb +66 -31
- data/lib/thrift/protocol/binary_protocol.rb +80 -37
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +7 -2
- data/lib/thrift/protocol/compact_protocol.rb +204 -88
- data/lib/thrift/protocol/header_protocol.rb +15 -3
- data/lib/thrift/protocol/json_protocol.rb +158 -109
- data/lib/thrift/protocol/multiplexed_protocol.rb +3 -3
- data/lib/thrift/protocol/protocol_decorator.rb +6 -2
- data/lib/thrift/serializer/deserializer.rb +1 -0
- data/lib/thrift/serializer/serializer.rb +7 -0
- data/lib/thrift/server/base_server.rb +11 -2
- data/lib/thrift/server/nonblocking_server.rb +69 -20
- data/lib/thrift/server/rack_application.rb +69 -0
- data/lib/thrift/server/simple_server.rb +27 -15
- data/lib/thrift/server/thin_http_server.rb +21 -44
- data/lib/thrift/server/thread_pool_server.rb +21 -17
- data/lib/thrift/server/threaded_server.rb +22 -18
- data/lib/thrift/struct.rb +34 -18
- data/lib/thrift/struct_union.rb +37 -36
- data/lib/thrift/thrift_native.rb +2 -1
- data/lib/thrift/transport/base_server_transport.rb +3 -0
- data/lib/thrift/transport/base_transport.rb +26 -4
- data/lib/thrift/transport/buffered_transport.rb +5 -4
- data/lib/thrift/transport/framed_transport.rb +33 -7
- data/lib/thrift/transport/header_transport.rb +159 -33
- data/lib/thrift/transport/http_client_transport.rb +28 -14
- data/lib/thrift/transport/io_stream_transport.rb +3 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +14 -9
- data/lib/thrift/transport/server_socket.rb +10 -8
- data/lib/thrift/transport/socket.rb +85 -48
- data/lib/thrift/transport/ssl_server_socket.rb +67 -6
- data/lib/thrift/transport/ssl_socket.rb +73 -14
- data/lib/thrift/transport/unix_server_socket.rb +6 -2
- data/lib/thrift/transport/unix_socket.rb +5 -6
- data/lib/thrift/types.rb +23 -22
- data/lib/thrift/union.rb +21 -11
- data/lib/thrift/uuid.rb +9 -8
- data/lib/thrift.rb +40 -39
- metadata +7 -266
- data/benchmark/Benchmark.thrift +0 -24
- data/benchmark/benchmark.rb +0 -285
- data/benchmark/client.rb +0 -117
- data/benchmark/server.rb +0 -120
- data/benchmark/thin_server.rb +0 -45
- data/lib/thrift/server/mongrel_http_server.rb +0 -60
- data/spec/BaseService.thrift +0 -27
- data/spec/ExtendedService.thrift +0 -25
- data/spec/Referenced.thrift +0 -44
- data/spec/ThriftNamespacedSpec.thrift +0 -53
- data/spec/ThriftSpec.thrift +0 -187
- data/spec/base_protocol_spec.rb +0 -224
- data/spec/base_transport_spec.rb +0 -387
- data/spec/binary_protocol_accelerated_spec.rb +0 -46
- data/spec/binary_protocol_spec.rb +0 -72
- data/spec/binary_protocol_spec_shared.rb +0 -445
- data/spec/bytes_spec.rb +0 -99
- data/spec/client_spec.rb +0 -166
- data/spec/compact_protocol_spec.rb +0 -196
- data/spec/constants_demo_spec.rb +0 -101
- data/spec/exception_spec.rb +0 -140
- data/spec/flat_spec.rb +0 -62
- data/spec/header_protocol_spec.rb +0 -475
- data/spec/header_transport_spec.rb +0 -386
- data/spec/http_client_spec.rb +0 -159
- data/spec/json_protocol_spec.rb +0 -552
- data/spec/namespaced_spec.rb +0 -66
- data/spec/nonblocking_server_spec.rb +0 -361
- data/spec/processor_spec.rb +0 -79
- data/spec/serializer_spec.rb +0 -66
- data/spec/server_socket_spec.rb +0 -84
- data/spec/server_spec.rb +0 -186
- data/spec/socket_spec.rb +0 -67
- data/spec/socket_spec_shared.rb +0 -167
- data/spec/spec_helper.rb +0 -69
- data/spec/ssl_server_socket_spec.rb +0 -45
- data/spec/ssl_socket_spec.rb +0 -87
- data/spec/struct_nested_containers_spec.rb +0 -190
- data/spec/struct_spec.rb +0 -397
- data/spec/support/header_protocol_helper.rb +0 -54
- data/spec/thin_http_server_spec.rb +0 -126
- data/spec/types_spec.rb +0 -117
- data/spec/union_spec.rb +0 -272
- data/spec/unix_socket_spec.rb +0 -115
- data/spec/uuid_validation_spec.rb +0 -238
- data/test/fuzz/Makefile.am +0 -173
- data/test/fuzz/README.md +0 -149
- data/test/fuzz/fuzz_common.rb +0 -95
- data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_tracer.rb +0 -28
data/lib/thrift/struct.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -17,7 +18,8 @@
|
|
|
17
18
|
# under the License.
|
|
18
19
|
#
|
|
19
20
|
|
|
20
|
-
require
|
|
21
|
+
require "set"
|
|
22
|
+
require "thrift/struct_union"
|
|
21
23
|
|
|
22
24
|
module Thrift
|
|
23
25
|
module Struct
|
|
@@ -51,7 +53,7 @@ module Thrift
|
|
|
51
53
|
end
|
|
52
54
|
end
|
|
53
55
|
|
|
54
|
-
yield self if
|
|
56
|
+
yield self if block
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
def fields_with_default_values
|
|
@@ -80,19 +82,31 @@ module Thrift
|
|
|
80
82
|
"<#{self.class} #{fields.join(", ")}>"
|
|
81
83
|
end
|
|
82
84
|
|
|
83
|
-
def read(iprot)
|
|
85
|
+
def read(iprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
86
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
87
|
+
unless instance_variables.empty?
|
|
88
|
+
defaults = fields_with_default_values
|
|
89
|
+
struct_fields.each_value do |field_info|
|
|
90
|
+
instance_variable_set("@#{field_info[:name]}", nil)
|
|
91
|
+
end
|
|
92
|
+
defaults.each do |name, default_value|
|
|
93
|
+
instance_variable_set("@#{name}", (default_value.dup rescue default_value))
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
84
97
|
iprot.read_struct_begin
|
|
85
98
|
loop do
|
|
86
|
-
|
|
99
|
+
_, ftype, fid = iprot.read_field_begin
|
|
87
100
|
break if (ftype == Types::STOP)
|
|
88
|
-
handle_message(iprot, fid, ftype)
|
|
101
|
+
handle_message(iprot, fid, ftype, remaining_depth)
|
|
89
102
|
iprot.read_field_end
|
|
90
103
|
end
|
|
91
104
|
iprot.read_struct_end
|
|
92
105
|
validate
|
|
93
106
|
end
|
|
94
107
|
|
|
95
|
-
def write(oprot)
|
|
108
|
+
def write(oprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
109
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
96
110
|
validate
|
|
97
111
|
oprot.write_struct_begin(self.class.name)
|
|
98
112
|
each_field do |fid, field_info|
|
|
@@ -102,8 +116,10 @@ module Thrift
|
|
|
102
116
|
unless value.nil?
|
|
103
117
|
if is_container? type
|
|
104
118
|
oprot.write_field_begin(name, type, fid)
|
|
105
|
-
write_container(oprot, value, field_info)
|
|
119
|
+
write_container(oprot, value, field_info, remaining_depth)
|
|
106
120
|
oprot.write_field_end
|
|
121
|
+
elsif type == Types::STRUCT
|
|
122
|
+
oprot.write_field(field_info, fid, value, remaining_depth)
|
|
107
123
|
else
|
|
108
124
|
oprot.write_field(field_info, fid, value)
|
|
109
125
|
end
|
|
@@ -114,10 +130,10 @@ module Thrift
|
|
|
114
130
|
end
|
|
115
131
|
|
|
116
132
|
def ==(other)
|
|
117
|
-
return false
|
|
133
|
+
return false unless other.instance_of?(self.class)
|
|
118
134
|
each_field do |fid, field_info|
|
|
119
135
|
name = field_info[:name]
|
|
120
|
-
return false unless other.respond_to?(name) &&
|
|
136
|
+
return false unless other.respond_to?(name) && send(name) == other.send(name)
|
|
121
137
|
end
|
|
122
138
|
true
|
|
123
139
|
end
|
|
@@ -131,8 +147,8 @@ module Thrift
|
|
|
131
147
|
total = 17
|
|
132
148
|
each_field do |fid, field_info|
|
|
133
149
|
name = field_info[:name]
|
|
134
|
-
value =
|
|
135
|
-
total = (total * 37 + value.hash) & 0xffffffff
|
|
150
|
+
value = send(name)
|
|
151
|
+
total = ((total * 37) + value.hash) & 0xffffffff
|
|
136
152
|
end
|
|
137
153
|
total
|
|
138
154
|
end
|
|
@@ -144,7 +160,7 @@ module Thrift
|
|
|
144
160
|
else
|
|
145
161
|
each_field do |fid, field_info|
|
|
146
162
|
name = field_info[:name]
|
|
147
|
-
diffs << "#{name} differs!" unless
|
|
163
|
+
diffs << "#{name} differs!" unless instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}")
|
|
148
164
|
end
|
|
149
165
|
end
|
|
150
166
|
diffs
|
|
@@ -168,14 +184,14 @@ module Thrift
|
|
|
168
184
|
|
|
169
185
|
def self.qmark_isset_method(klass, field_info)
|
|
170
186
|
klass.send :define_method, "#{field_info[:name]}?" do
|
|
171
|
-
!
|
|
187
|
+
!send(field_info[:name].to_sym).nil?
|
|
172
188
|
end
|
|
173
189
|
end
|
|
174
190
|
|
|
175
191
|
def <=>(other)
|
|
176
192
|
if self.class == other.class
|
|
177
193
|
each_field do |fid, field_info|
|
|
178
|
-
v1 =
|
|
194
|
+
v1 = send(field_info[:name])
|
|
179
195
|
v1_set = !v1.nil?
|
|
180
196
|
v2 = other.send(field_info[:name])
|
|
181
197
|
v2_set = !v2.nil?
|
|
@@ -217,17 +233,17 @@ module Thrift
|
|
|
217
233
|
else
|
|
218
234
|
# call the Struct initializer first with no args
|
|
219
235
|
# this will set our field default values
|
|
220
|
-
method(:struct_initialize).call
|
|
236
|
+
method(:struct_initialize).call
|
|
221
237
|
# now give it to the exception
|
|
222
|
-
self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').
|
|
238
|
+
self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').bind_call(self, *args, &block) if args.size > 0
|
|
223
239
|
# self.class.instance_method(:initialize).bind(self).call(*args, &block)
|
|
224
240
|
end
|
|
225
241
|
end
|
|
226
242
|
|
|
227
|
-
def handle_message(iprot, fid, ftype)
|
|
243
|
+
def handle_message(iprot, fid, ftype, remaining_depth)
|
|
228
244
|
field = struct_fields[fid]
|
|
229
245
|
if field and field[:type] == ftype
|
|
230
|
-
value = read_field(iprot, field)
|
|
246
|
+
value = read_field(iprot, field, remaining_depth)
|
|
231
247
|
instance_variable_set("@#{field[:name]}", value)
|
|
232
248
|
else
|
|
233
249
|
iprot.skip(ftype)
|
data/lib/thrift/struct_union.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -16,16 +17,12 @@
|
|
|
16
17
|
# specific language governing permissions and limitations
|
|
17
18
|
# under the License.
|
|
18
19
|
#
|
|
19
|
-
require
|
|
20
|
+
require "set"
|
|
21
|
+
require "thrift/exceptions"
|
|
22
|
+
require "thrift/types"
|
|
20
23
|
|
|
21
24
|
module Thrift
|
|
22
25
|
module Struct_Union
|
|
23
|
-
def validate_container_size(size)
|
|
24
|
-
return size unless size < 0
|
|
25
|
-
|
|
26
|
-
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size')
|
|
27
|
-
end
|
|
28
|
-
|
|
29
26
|
def name_to_id(name)
|
|
30
27
|
names_to_ids = self.class.instance_variable_get(:@names_to_ids)
|
|
31
28
|
unless names_to_ids
|
|
@@ -54,16 +51,17 @@ module Thrift
|
|
|
54
51
|
end
|
|
55
52
|
end
|
|
56
53
|
|
|
57
|
-
def read_field(iprot, field = {})
|
|
54
|
+
def read_field(iprot, field = {}, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
58
55
|
case field[:type]
|
|
59
56
|
when Types::STRUCT
|
|
57
|
+
remaining_depth -= 1
|
|
60
58
|
value = field[:class].new
|
|
61
|
-
value.read(iprot)
|
|
59
|
+
value.read(iprot, remaining_depth)
|
|
62
60
|
when Types::MAP
|
|
63
61
|
key_type, val_type, size = iprot.read_map_begin
|
|
64
|
-
validate_container_size(size)
|
|
62
|
+
iprot.validate_container_size(size)
|
|
65
63
|
# Skip the map contents if the declared key or value types don't match the expected ones.
|
|
66
|
-
if
|
|
64
|
+
if size != 0 && (key_type != field[:key][:type] || val_type != field[:value][:type])
|
|
67
65
|
size.times do
|
|
68
66
|
iprot.skip(key_type)
|
|
69
67
|
iprot.skip(val_type)
|
|
@@ -72,15 +70,15 @@ module Thrift
|
|
|
72
70
|
else
|
|
73
71
|
value = {}
|
|
74
72
|
size.times do
|
|
75
|
-
k = read_field(iprot, field_info(field[:key]))
|
|
76
|
-
v = read_field(iprot, field_info(field[:value]))
|
|
73
|
+
k = read_field(iprot, field_info(field[:key]), remaining_depth)
|
|
74
|
+
v = read_field(iprot, field_info(field[:value]), remaining_depth)
|
|
77
75
|
value[k] = v
|
|
78
76
|
end
|
|
79
77
|
end
|
|
80
78
|
iprot.read_map_end
|
|
81
79
|
when Types::LIST
|
|
82
80
|
e_type, size = iprot.read_list_begin
|
|
83
|
-
validate_container_size(size)
|
|
81
|
+
iprot.validate_container_size(size)
|
|
84
82
|
# Skip the list contents if the declared element type doesn't match the expected one.
|
|
85
83
|
if (e_type != field[:element][:type])
|
|
86
84
|
size.times do
|
|
@@ -90,13 +88,13 @@ module Thrift
|
|
|
90
88
|
else
|
|
91
89
|
value = []
|
|
92
90
|
size.times do
|
|
93
|
-
value << read_field(iprot, field_info(field[:element]))
|
|
91
|
+
value << read_field(iprot, field_info(field[:element]), remaining_depth)
|
|
94
92
|
end
|
|
95
93
|
end
|
|
96
94
|
iprot.read_list_end
|
|
97
95
|
when Types::SET
|
|
98
96
|
e_type, size = iprot.read_set_begin
|
|
99
|
-
validate_container_size(size)
|
|
97
|
+
iprot.validate_container_size(size)
|
|
100
98
|
# Skip the set contents if the declared element type doesn't match the expected one.
|
|
101
99
|
if (e_type != field[:element][:type])
|
|
102
100
|
size.times do
|
|
@@ -105,7 +103,7 @@ module Thrift
|
|
|
105
103
|
else
|
|
106
104
|
value = Set.new
|
|
107
105
|
size.times do
|
|
108
|
-
element = read_field(iprot, field_info(field[:element]))
|
|
106
|
+
element = read_field(iprot, field_info(field[:element]), remaining_depth)
|
|
109
107
|
value << element
|
|
110
108
|
end
|
|
111
109
|
end
|
|
@@ -116,33 +114,36 @@ module Thrift
|
|
|
116
114
|
value
|
|
117
115
|
end
|
|
118
116
|
|
|
119
|
-
def write_data(oprot, value, field)
|
|
117
|
+
def write_data(oprot, value, field, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
120
118
|
if is_container? field[:type]
|
|
121
|
-
write_container(oprot, value, field)
|
|
119
|
+
write_container(oprot, value, field, remaining_depth)
|
|
120
|
+
elsif field[:type] == Types::STRUCT
|
|
121
|
+
remaining_depth -= 1
|
|
122
|
+
value.write(oprot, remaining_depth)
|
|
122
123
|
else
|
|
123
124
|
oprot.write_type(field, value)
|
|
124
125
|
end
|
|
125
126
|
end
|
|
126
127
|
|
|
127
|
-
def write_container(oprot, value, field = {})
|
|
128
|
+
def write_container(oprot, value, field = {}, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
128
129
|
case field[:type]
|
|
129
130
|
when Types::MAP
|
|
130
131
|
oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size)
|
|
131
132
|
value.each do |k, v|
|
|
132
|
-
write_data(oprot, k, field[:key])
|
|
133
|
-
write_data(oprot, v, field[:value])
|
|
133
|
+
write_data(oprot, k, field[:key], remaining_depth)
|
|
134
|
+
write_data(oprot, v, field[:value], remaining_depth)
|
|
134
135
|
end
|
|
135
136
|
oprot.write_map_end
|
|
136
137
|
when Types::LIST
|
|
137
138
|
oprot.write_list_begin(field[:element][:type], value.size)
|
|
138
139
|
value.each do |elem|
|
|
139
|
-
write_data(oprot, elem, field[:element])
|
|
140
|
+
write_data(oprot, elem, field[:element], remaining_depth)
|
|
140
141
|
end
|
|
141
142
|
oprot.write_list_end
|
|
142
143
|
when Types::SET
|
|
143
144
|
oprot.write_set_begin(field[:element][:type], value.size)
|
|
144
145
|
value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets
|
|
145
|
-
write_data(oprot, v, field[:element])
|
|
146
|
+
write_data(oprot, v, field[:element], remaining_depth)
|
|
146
147
|
end
|
|
147
148
|
oprot.write_set_end
|
|
148
149
|
else
|
|
@@ -159,11 +160,13 @@ module Thrift
|
|
|
159
160
|
end
|
|
160
161
|
|
|
161
162
|
def field_info(field)
|
|
162
|
-
{
|
|
163
|
-
:
|
|
164
|
-
:
|
|
165
|
-
:
|
|
166
|
-
:
|
|
163
|
+
{
|
|
164
|
+
type: field[:type],
|
|
165
|
+
class: field[:class],
|
|
166
|
+
key: field[:key],
|
|
167
|
+
value: field[:value],
|
|
168
|
+
element: field[:element],
|
|
169
|
+
}
|
|
167
170
|
end
|
|
168
171
|
|
|
169
172
|
def inspect_field(value, field_info)
|
|
@@ -171,9 +174,8 @@ module Thrift
|
|
|
171
174
|
"#{enum_class.const_get(:VALUE_MAP)[value]} (#{value})"
|
|
172
175
|
elsif value.is_a? Hash
|
|
173
176
|
if field_info[:type] == Types::MAP
|
|
174
|
-
map_buf =
|
|
175
|
-
|
|
176
|
-
map_buf << inspect_field(k, field_info[:key]) + ": " + inspect_field(v, field_info[:value])
|
|
177
|
+
map_buf = value.map do |k, v|
|
|
178
|
+
inspect_field(k, field_info[:key]) + ": " + inspect_field(v, field_info[:value])
|
|
177
179
|
end
|
|
178
180
|
"{" + map_buf.join(", ") + "}"
|
|
179
181
|
else
|
|
@@ -185,16 +187,15 @@ module Thrift
|
|
|
185
187
|
elsif value.is_a? Set
|
|
186
188
|
inspect_collection(value, field_info)
|
|
187
189
|
elsif value.is_a?(String) && field_info[:binary]
|
|
188
|
-
value.
|
|
190
|
+
value.unpack1("H*")
|
|
189
191
|
else
|
|
190
192
|
value.inspect
|
|
191
193
|
end
|
|
192
194
|
end
|
|
193
195
|
|
|
194
196
|
def inspect_collection(collection, field_info)
|
|
195
|
-
buf =
|
|
196
|
-
|
|
197
|
-
buf << inspect_field(k, field_info[:element])
|
|
197
|
+
buf = collection.map do |element|
|
|
198
|
+
inspect_field(element, field_info[:element])
|
|
198
199
|
end
|
|
199
200
|
"[" + buf.join(", ") + "]"
|
|
200
201
|
end
|
data/lib/thrift/thrift_native.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -20,5 +21,5 @@
|
|
|
20
21
|
begin
|
|
21
22
|
require "thrift_native"
|
|
22
23
|
rescue LoadError
|
|
23
|
-
|
|
24
|
+
warn "Unable to load thrift_native extension. Defaulting to pure Ruby libraries."
|
|
24
25
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -20,6 +21,8 @@
|
|
|
20
21
|
|
|
21
22
|
module Thrift
|
|
22
23
|
class BaseServerTransport
|
|
24
|
+
DEFAULT_CLIENT_TIMEOUT = 5
|
|
25
|
+
|
|
23
26
|
def listen
|
|
24
27
|
raise NotImplementedError
|
|
25
28
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -25,6 +26,8 @@ module Thrift
|
|
|
25
26
|
ALREADY_OPEN = 2
|
|
26
27
|
TIMED_OUT = 3
|
|
27
28
|
END_OF_FILE = 4
|
|
29
|
+
NEGATIVE_SIZE = 5
|
|
30
|
+
SIZE_LIMIT = 6
|
|
28
31
|
|
|
29
32
|
attr_reader :type
|
|
30
33
|
|
|
@@ -53,6 +56,11 @@ module Thrift
|
|
|
53
56
|
|
|
54
57
|
def close; end
|
|
55
58
|
|
|
59
|
+
# Returns true when the transport needs protocol message boundary notifications.
|
|
60
|
+
def message_boundaries?
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
|
|
56
64
|
# Reads a number of bytes from the transports. The String returned will have a BINARY (aka ASCII-8BIT) encoding.
|
|
57
65
|
#
|
|
58
66
|
# sz - The number of bytes to read from the transport.
|
|
@@ -65,7 +73,7 @@ module Thrift
|
|
|
65
73
|
# Returns an unsigned byte as a Integer in the range (0..255).
|
|
66
74
|
def read_byte
|
|
67
75
|
buf = read_all(1)
|
|
68
|
-
|
|
76
|
+
Bytes.get_string_byte(buf, 0)
|
|
69
77
|
end
|
|
70
78
|
|
|
71
79
|
# Reads size bytes and copies them into buffer[0..size].
|
|
@@ -80,11 +88,25 @@ module Thrift
|
|
|
80
88
|
end
|
|
81
89
|
|
|
82
90
|
def read_all(size)
|
|
83
|
-
|
|
91
|
+
raise TransportException.new(TransportException::NEGATIVE_SIZE, "Negative size") unless size >= 0
|
|
92
|
+
return Bytes.empty_byte_buffer if size == 0
|
|
93
|
+
|
|
84
94
|
buf = read(size)
|
|
95
|
+
if buf.nil? || buf.empty?
|
|
96
|
+
raise TransportException.new(TransportException::END_OF_FILE, "No more data available")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
buf = Bytes.force_binary_encoding(buf)
|
|
100
|
+
return buf if buf.length >= size
|
|
101
|
+
|
|
102
|
+
buf = buf.dup if buf.frozen?
|
|
85
103
|
while (buf.length < size)
|
|
86
104
|
chunk = read(size - buf.length)
|
|
87
|
-
|
|
105
|
+
if chunk.nil? || chunk.empty?
|
|
106
|
+
raise TransportException.new(TransportException::END_OF_FILE, "No more data available")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
buf << Bytes.force_binary_encoding(chunk)
|
|
88
110
|
end
|
|
89
111
|
|
|
90
112
|
buf
|
|
@@ -107,7 +129,7 @@ module Thrift
|
|
|
107
129
|
|
|
108
130
|
class BaseTransportFactory
|
|
109
131
|
def get_transport(trans)
|
|
110
|
-
|
|
132
|
+
trans
|
|
111
133
|
end
|
|
112
134
|
|
|
113
135
|
def to_s
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -30,7 +31,7 @@ module Thrift
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def open?
|
|
33
|
-
|
|
34
|
+
@transport.open?
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
def open
|
|
@@ -65,7 +66,7 @@ module Thrift
|
|
|
65
66
|
# The read buffer has some data now, read a single byte. Using get_string_byte() avoids
|
|
66
67
|
# allocating a temp string of size 1 unnecessarily.
|
|
67
68
|
@index += 1
|
|
68
|
-
|
|
69
|
+
Bytes.get_string_byte(@rbuf, @index - 1)
|
|
69
70
|
end
|
|
70
71
|
|
|
71
72
|
# Reads a number of bytes from the transport into the buffer passed.
|
|
@@ -106,13 +107,13 @@ module Thrift
|
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
def to_s
|
|
109
|
-
"buffered(#{@transport
|
|
110
|
+
"buffered(#{@transport})"
|
|
110
111
|
end
|
|
111
112
|
end
|
|
112
113
|
|
|
113
114
|
class BufferedTransportFactory < BaseTransportFactory
|
|
114
115
|
def get_transport(transport)
|
|
115
|
-
|
|
116
|
+
BufferedTransport.new(transport)
|
|
116
117
|
end
|
|
117
118
|
|
|
118
119
|
def to_s
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -20,15 +21,30 @@
|
|
|
20
21
|
|
|
21
22
|
module Thrift
|
|
22
23
|
class FramedTransport < BaseTransport
|
|
23
|
-
|
|
24
|
+
# The largest frame accepted by default. The value the Java, netstd, C++
|
|
25
|
+
# and Python framed transports use.
|
|
26
|
+
DEFAULT_MAX_FRAME_SIZE = 16_384_000
|
|
27
|
+
|
|
28
|
+
# The frame length field is 30 bits, so no frame can usefully be larger
|
|
29
|
+
# than this whatever a caller configures.
|
|
30
|
+
HARD_MAX_FRAME_SIZE = 0x3FFFFFFF
|
|
31
|
+
|
|
32
|
+
def initialize(transport, read = true, write = true, max_frame_size: DEFAULT_MAX_FRAME_SIZE)
|
|
33
|
+
unless max_frame_size > 0 && max_frame_size <= HARD_MAX_FRAME_SIZE
|
|
34
|
+
raise ArgumentError, "max_frame_size must be > 0 and <= #{HARD_MAX_FRAME_SIZE}"
|
|
35
|
+
end
|
|
36
|
+
|
|
24
37
|
@transport = transport
|
|
25
38
|
@rbuf = Bytes.empty_byte_buffer
|
|
26
39
|
@wbuf = Bytes.empty_byte_buffer
|
|
27
40
|
@read = read
|
|
28
41
|
@write = write
|
|
29
42
|
@index = 0
|
|
43
|
+
@max_frame_size = max_frame_size
|
|
30
44
|
end
|
|
31
45
|
|
|
46
|
+
attr_reader :max_frame_size
|
|
47
|
+
|
|
32
48
|
def open?
|
|
33
49
|
@transport.open?
|
|
34
50
|
end
|
|
@@ -53,14 +69,14 @@ module Thrift
|
|
|
53
69
|
end
|
|
54
70
|
|
|
55
71
|
def read_byte
|
|
56
|
-
return @transport.read_byte
|
|
72
|
+
return @transport.read_byte unless @read
|
|
57
73
|
|
|
58
74
|
read_frame if @index >= @rbuf.length
|
|
59
75
|
|
|
60
76
|
# The read buffer has some data now, read a single byte. Using get_string_byte() avoids
|
|
61
77
|
# allocating a temp string of size 1 unnecessarily.
|
|
62
78
|
@index += 1
|
|
63
|
-
|
|
79
|
+
Bytes.get_string_byte(@rbuf, @index - 1)
|
|
64
80
|
end
|
|
65
81
|
|
|
66
82
|
def read_into_buffer(buffer, size)
|
|
@@ -91,7 +107,7 @@ module Thrift
|
|
|
91
107
|
def flush
|
|
92
108
|
return @transport.flush unless @write
|
|
93
109
|
|
|
94
|
-
out = [@wbuf.length].pack(
|
|
110
|
+
out = [@wbuf.length].pack("N")
|
|
95
111
|
# Array#pack should return a BINARY encoded String, so it shouldn't be necessary to force encoding
|
|
96
112
|
out << @wbuf
|
|
97
113
|
@transport.write(out)
|
|
@@ -100,13 +116,23 @@ module Thrift
|
|
|
100
116
|
end
|
|
101
117
|
|
|
102
118
|
def to_s
|
|
103
|
-
"framed(#{@transport
|
|
119
|
+
"framed(#{@transport})"
|
|
104
120
|
end
|
|
105
121
|
|
|
106
122
|
private
|
|
107
123
|
|
|
108
124
|
def read_frame
|
|
109
|
-
sz = @transport.read_all(4).
|
|
125
|
+
sz = @transport.read_all(4).unpack1("N")
|
|
126
|
+
raise TransportException.new(TransportException::END_OF_FILE, "Cannot read from a zero-length frame") if sz == 0
|
|
127
|
+
|
|
128
|
+
# Checked before the read, not after: read_all accumulates whatever the
|
|
129
|
+
# four bytes declare while the peer decides how much of it to send.
|
|
130
|
+
if sz > @max_frame_size
|
|
131
|
+
raise TransportException.new(
|
|
132
|
+
TransportException::UNKNOWN,
|
|
133
|
+
"Frame size #{sz} exceeds maximum #{@max_frame_size}",
|
|
134
|
+
)
|
|
135
|
+
end
|
|
110
136
|
|
|
111
137
|
@index = 0
|
|
112
138
|
@rbuf = @transport.read_all(sz)
|
|
@@ -115,7 +141,7 @@ module Thrift
|
|
|
115
141
|
|
|
116
142
|
class FramedTransportFactory < BaseTransportFactory
|
|
117
143
|
def get_transport(transport)
|
|
118
|
-
|
|
144
|
+
FramedTransport.new(transport)
|
|
119
145
|
end
|
|
120
146
|
|
|
121
147
|
def to_s
|