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
|
@@ -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
|
|
@@ -19,13 +20,24 @@
|
|
|
19
20
|
|
|
20
21
|
module Thrift
|
|
21
22
|
class CompactProtocol < BaseProtocol
|
|
22
|
-
|
|
23
|
-
PROTOCOL_ID = [0x82].pack('c').unpack('c').first
|
|
23
|
+
PROTOCOL_ID = [0x82].pack("c").unpack1("c")
|
|
24
24
|
VERSION = 1
|
|
25
25
|
VERSION_MASK = 0x1f
|
|
26
26
|
TYPE_MASK = 0xE0
|
|
27
27
|
TYPE_BITS = 0x07
|
|
28
28
|
TYPE_SHIFT_AMOUNT = 5
|
|
29
|
+
MAX_VARINT32_BYTES = 5 # ceil(32/7); matches protobuf wire format
|
|
30
|
+
VARINT32_PREFIX_BYTES = MAX_VARINT32_BYTES - 1
|
|
31
|
+
MAX_VARINT32_LAST_BYTE = 0x0f
|
|
32
|
+
MAX_VARINT_BYTES = 10 # ceil(64/7); matches protobuf wire format
|
|
33
|
+
BYTE_MIN = -(2**7)
|
|
34
|
+
BYTE_MAX = (2**7) - 1
|
|
35
|
+
I16_MIN = -(2**15)
|
|
36
|
+
I16_MAX = (2**15) - 1
|
|
37
|
+
I32_MIN = -(2**31)
|
|
38
|
+
I32_MAX = (2**31) - 1
|
|
39
|
+
I64_MIN = -(2**63)
|
|
40
|
+
I64_MAX = (2**63) - 1
|
|
29
41
|
|
|
30
42
|
TSTOP = [nil, Types::STOP, 0]
|
|
31
43
|
|
|
@@ -65,40 +77,53 @@ module Thrift
|
|
|
65
77
|
SET => Types::SET,
|
|
66
78
|
MAP => Types::MAP,
|
|
67
79
|
STRUCT => Types::STRUCT,
|
|
68
|
-
UUID => Types::UUID
|
|
80
|
+
UUID => Types::UUID,
|
|
69
81
|
}
|
|
70
82
|
|
|
71
83
|
TTYPE_TO_COMPACT = {
|
|
72
|
-
Types::STOP
|
|
73
|
-
Types::BOOL
|
|
74
|
-
Types::BYTE
|
|
75
|
-
Types::I16
|
|
76
|
-
Types::I32
|
|
77
|
-
Types::I64
|
|
78
|
-
Types::DOUBLE
|
|
79
|
-
Types::STRING
|
|
80
|
-
Types::LIST
|
|
81
|
-
Types::SET
|
|
82
|
-
Types::MAP
|
|
83
|
-
Types::STRUCT
|
|
84
|
-
Types::UUID
|
|
84
|
+
Types::STOP => Types::STOP,
|
|
85
|
+
Types::BOOL => BOOLEAN_TRUE,
|
|
86
|
+
Types::BYTE => BYTE,
|
|
87
|
+
Types::I16 => I16,
|
|
88
|
+
Types::I32 => I32,
|
|
89
|
+
Types::I64 => I64,
|
|
90
|
+
Types::DOUBLE => DOUBLE,
|
|
91
|
+
Types::STRING => BINARY,
|
|
92
|
+
Types::LIST => LIST,
|
|
93
|
+
Types::SET => SET,
|
|
94
|
+
Types::MAP => MAP,
|
|
95
|
+
Types::STRUCT => STRUCT,
|
|
96
|
+
Types::UUID => UUID,
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
def self.get_ttype(compact_type)
|
|
88
100
|
val = COMPACT_TO_TTYPE[compact_type & 0x0f]
|
|
89
|
-
|
|
90
|
-
|
|
101
|
+
return val if val
|
|
102
|
+
|
|
103
|
+
raise ProtocolException.new(
|
|
104
|
+
ProtocolException::INVALID_DATA,
|
|
105
|
+
"Unknown compact type: #{compact_type & 0x0f}",
|
|
106
|
+
)
|
|
91
107
|
end
|
|
92
108
|
|
|
93
109
|
def self.get_compact_type(ttype)
|
|
94
110
|
val = TTYPE_TO_COMPACT[ttype]
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
return val if val
|
|
112
|
+
|
|
113
|
+
raise ProtocolException.new(
|
|
114
|
+
ProtocolException::INVALID_DATA,
|
|
115
|
+
"Unknown compact type: #{ttype}",
|
|
116
|
+
)
|
|
97
117
|
end
|
|
98
118
|
end
|
|
99
119
|
|
|
100
|
-
|
|
120
|
+
attr_reader :max_string_size
|
|
121
|
+
|
|
122
|
+
def initialize(transport, max_string_size: DEFAULT_MAX_STRING_SIZE)
|
|
123
|
+
BaseProtocol.validate_max_string_size(max_string_size)
|
|
101
124
|
super(transport)
|
|
125
|
+
@max_string_size = max_string_size
|
|
126
|
+
@reset_message_size = transport.message_boundaries?
|
|
102
127
|
|
|
103
128
|
@last_field = [0]
|
|
104
129
|
@boolean_value = nil
|
|
@@ -108,8 +133,14 @@ module Thrift
|
|
|
108
133
|
end
|
|
109
134
|
|
|
110
135
|
def write_message_begin(name, type, seqid)
|
|
111
|
-
|
|
112
|
-
|
|
136
|
+
unless seqid.is_a?(Integer)
|
|
137
|
+
raise "nil argument not allowed!" if seqid.nil?
|
|
138
|
+
raise ::TypeError, "integer argument expected"
|
|
139
|
+
end
|
|
140
|
+
raise RangeError if seqid < I32_MIN || seqid > I32_MAX
|
|
141
|
+
|
|
142
|
+
write_byte_direct(PROTOCOL_ID)
|
|
143
|
+
write_byte_direct((VERSION & VERSION_MASK) | ((type << TYPE_SHIFT_AMOUNT) & TYPE_MASK))
|
|
113
144
|
write_varint32(message_seqid_to_varint32(seqid))
|
|
114
145
|
write_string(name)
|
|
115
146
|
nil
|
|
@@ -126,6 +157,12 @@ module Thrift
|
|
|
126
157
|
end
|
|
127
158
|
|
|
128
159
|
def write_field_begin(name, type, id)
|
|
160
|
+
unless id.is_a?(Integer)
|
|
161
|
+
raise "nil argument not allowed!" if id.nil?
|
|
162
|
+
raise ::TypeError, "integer argument expected"
|
|
163
|
+
end
|
|
164
|
+
raise RangeError if id < I16_MIN || id > I16_MAX
|
|
165
|
+
|
|
129
166
|
if type == Types::BOOL
|
|
130
167
|
# we want to possibly include the value, so we'll wait.
|
|
131
168
|
@boolean_field = [type, id]
|
|
@@ -144,16 +181,16 @@ module Thrift
|
|
|
144
181
|
last_id = @last_field.pop
|
|
145
182
|
|
|
146
183
|
# if there's a type override, use that.
|
|
147
|
-
|
|
184
|
+
type_to_write = type_override || CompactTypes.get_compact_type(type)
|
|
148
185
|
|
|
149
186
|
# check if we can use delta encoding for the field id
|
|
150
187
|
if id > last_id && id - last_id <= 15
|
|
151
188
|
# write them together
|
|
152
|
-
|
|
189
|
+
write_byte_direct(((id - last_id) << 4) | type_to_write)
|
|
153
190
|
else
|
|
154
191
|
# write them separate
|
|
155
|
-
|
|
156
|
-
|
|
192
|
+
write_byte_direct(type_to_write)
|
|
193
|
+
write_varint32(int_to_zig_zag(id))
|
|
157
194
|
end
|
|
158
195
|
|
|
159
196
|
@last_field.push(id)
|
|
@@ -161,15 +198,16 @@ module Thrift
|
|
|
161
198
|
end
|
|
162
199
|
|
|
163
200
|
def write_field_stop
|
|
164
|
-
|
|
201
|
+
write_byte_direct(Types::STOP)
|
|
165
202
|
end
|
|
166
203
|
|
|
167
204
|
def write_map_begin(ktype, vtype, size)
|
|
205
|
+
size = validate_size(size)
|
|
168
206
|
if (size == 0)
|
|
169
|
-
|
|
207
|
+
write_byte_direct(0)
|
|
170
208
|
else
|
|
171
209
|
write_varint32(size)
|
|
172
|
-
|
|
210
|
+
write_byte_direct((CompactTypes.get_compact_type(ktype) << 4) | CompactTypes.get_compact_type(vtype))
|
|
173
211
|
end
|
|
174
212
|
end
|
|
175
213
|
|
|
@@ -182,6 +220,7 @@ module Thrift
|
|
|
182
220
|
end
|
|
183
221
|
|
|
184
222
|
def write_bool(bool)
|
|
223
|
+
# Preserve Ruby truthiness: only false and nil encode as false.
|
|
185
224
|
type = bool ? CompactTypes::BOOLEAN_TRUE : CompactTypes::BOOLEAN_FALSE
|
|
186
225
|
unless @boolean_field.nil?
|
|
187
226
|
# we haven't written the field header yet
|
|
@@ -189,23 +228,47 @@ module Thrift
|
|
|
189
228
|
@boolean_field = nil
|
|
190
229
|
else
|
|
191
230
|
# we're not part of a field, so just write the value.
|
|
192
|
-
|
|
231
|
+
write_byte_direct(type)
|
|
193
232
|
end
|
|
194
233
|
end
|
|
195
234
|
|
|
196
235
|
def write_byte(byte)
|
|
197
|
-
|
|
236
|
+
unless byte.is_a?(Integer)
|
|
237
|
+
raise "nil argument not allowed!" if byte.nil?
|
|
238
|
+
raise ::TypeError, "integer argument expected"
|
|
239
|
+
end
|
|
240
|
+
raise RangeError if byte < BYTE_MIN || byte > BYTE_MAX
|
|
241
|
+
|
|
242
|
+
write_byte_direct(byte)
|
|
198
243
|
end
|
|
199
244
|
|
|
200
245
|
def write_i16(i16)
|
|
246
|
+
unless i16.is_a?(Integer)
|
|
247
|
+
raise "nil argument not allowed!" if i16.nil?
|
|
248
|
+
raise ::TypeError, "integer argument expected"
|
|
249
|
+
end
|
|
250
|
+
raise RangeError if i16 < I16_MIN || i16 > I16_MAX
|
|
251
|
+
|
|
201
252
|
write_varint32(int_to_zig_zag(i16))
|
|
202
253
|
end
|
|
203
254
|
|
|
204
255
|
def write_i32(i32)
|
|
256
|
+
unless i32.is_a?(Integer)
|
|
257
|
+
raise "nil argument not allowed!" if i32.nil?
|
|
258
|
+
raise ::TypeError, "integer argument expected"
|
|
259
|
+
end
|
|
260
|
+
raise RangeError if i32 < I32_MIN || i32 > I32_MAX
|
|
261
|
+
|
|
205
262
|
write_varint32(int_to_zig_zag(i32))
|
|
206
263
|
end
|
|
207
264
|
|
|
208
265
|
def write_i64(i64)
|
|
266
|
+
unless i64.is_a?(Integer)
|
|
267
|
+
raise "nil argument not allowed!" if i64.nil?
|
|
268
|
+
raise ::TypeError, "integer argument expected"
|
|
269
|
+
end
|
|
270
|
+
raise RangeError if i64 < I64_MIN || i64 > I64_MAX
|
|
271
|
+
|
|
209
272
|
write_varint64(long_to_zig_zag(i64))
|
|
210
273
|
end
|
|
211
274
|
|
|
@@ -219,7 +282,8 @@ module Thrift
|
|
|
219
282
|
end
|
|
220
283
|
|
|
221
284
|
def write_binary(buf)
|
|
222
|
-
|
|
285
|
+
size = validate_size(buf.bytesize)
|
|
286
|
+
write_varint32(size)
|
|
223
287
|
@trans.write(buf)
|
|
224
288
|
end
|
|
225
289
|
|
|
@@ -229,20 +293,28 @@ module Thrift
|
|
|
229
293
|
end
|
|
230
294
|
|
|
231
295
|
def read_message_begin
|
|
232
|
-
|
|
296
|
+
trans.reset_message_size if @reset_message_size
|
|
297
|
+
|
|
298
|
+
protocol_id = read_byte
|
|
233
299
|
if protocol_id != PROTOCOL_ID
|
|
234
|
-
raise ProtocolException.new(
|
|
300
|
+
raise ProtocolException.new(
|
|
301
|
+
ProtocolException::BAD_VERSION,
|
|
302
|
+
"Expected protocol id #{PROTOCOL_ID} but got #{protocol_id}",
|
|
303
|
+
)
|
|
235
304
|
end
|
|
236
305
|
|
|
237
|
-
version_and_type = read_byte
|
|
306
|
+
version_and_type = read_byte
|
|
238
307
|
version = version_and_type & VERSION_MASK
|
|
239
308
|
if (version != VERSION)
|
|
240
|
-
raise ProtocolException.new(
|
|
309
|
+
raise ProtocolException.new(
|
|
310
|
+
ProtocolException::BAD_VERSION,
|
|
311
|
+
"Expected version #{VERSION} but got #{version}",
|
|
312
|
+
)
|
|
241
313
|
end
|
|
242
314
|
|
|
243
315
|
type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS
|
|
244
|
-
seqid = message_seqid_from_varint32(read_varint32
|
|
245
|
-
messageName = read_string
|
|
316
|
+
seqid = message_seqid_from_varint32(read_varint32)
|
|
317
|
+
messageName = read_string
|
|
246
318
|
[messageName, type, seqid]
|
|
247
319
|
end
|
|
248
320
|
|
|
@@ -252,12 +324,12 @@ module Thrift
|
|
|
252
324
|
end
|
|
253
325
|
|
|
254
326
|
def read_struct_end
|
|
255
|
-
@last_field.pop
|
|
327
|
+
@last_field.pop
|
|
256
328
|
nil
|
|
257
329
|
end
|
|
258
330
|
|
|
259
331
|
def read_field_begin
|
|
260
|
-
type = read_byte
|
|
332
|
+
type = read_byte
|
|
261
333
|
|
|
262
334
|
# if it's a stop, then we can return immediately, as the struct is over.
|
|
263
335
|
if (type & 0x0f) == Types::STOP
|
|
@@ -270,7 +342,7 @@ module Thrift
|
|
|
270
342
|
if modifier == 0
|
|
271
343
|
# not a delta. look ahead for the zigzag varint field id.
|
|
272
344
|
@last_field.pop
|
|
273
|
-
field_id = read_i16
|
|
345
|
+
field_id = read_i16
|
|
274
346
|
else
|
|
275
347
|
# has a delta. add the delta to the last read field id.
|
|
276
348
|
field_id = @last_field.pop + modifier
|
|
@@ -289,17 +361,19 @@ module Thrift
|
|
|
289
361
|
end
|
|
290
362
|
|
|
291
363
|
def read_map_begin
|
|
292
|
-
size = read_varint32
|
|
293
|
-
|
|
364
|
+
size = read_varint32
|
|
365
|
+
validate_container_size(size)
|
|
366
|
+
key_and_value_type = size == 0 ? 0 : read_byte
|
|
294
367
|
[CompactTypes.get_ttype(key_and_value_type >> 4), CompactTypes.get_ttype(key_and_value_type & 0xf), size]
|
|
295
368
|
end
|
|
296
369
|
|
|
297
370
|
def read_list_begin
|
|
298
|
-
size_and_type = read_byte
|
|
371
|
+
size_and_type = read_byte
|
|
299
372
|
size = (size_and_type >> 4) & 0x0f
|
|
300
373
|
if size == 15
|
|
301
|
-
size = read_varint32
|
|
374
|
+
size = read_varint32
|
|
302
375
|
end
|
|
376
|
+
validate_container_size(size)
|
|
303
377
|
type = CompactTypes.get_ttype(size_and_type)
|
|
304
378
|
[type, size]
|
|
305
379
|
end
|
|
@@ -314,7 +388,7 @@ module Thrift
|
|
|
314
388
|
@bool_value = nil
|
|
315
389
|
bv
|
|
316
390
|
else
|
|
317
|
-
read_byte
|
|
391
|
+
read_byte == CompactTypes::BOOLEAN_TRUE
|
|
318
392
|
end
|
|
319
393
|
end
|
|
320
394
|
|
|
@@ -327,21 +401,21 @@ module Thrift
|
|
|
327
401
|
end
|
|
328
402
|
|
|
329
403
|
def read_i16
|
|
330
|
-
zig_zag_to_int(read_varint32
|
|
404
|
+
value = zig_zag_to_int(read_varint32) & 0xffff
|
|
405
|
+
value > I16_MAX ? value - 0x10000 : value
|
|
331
406
|
end
|
|
332
407
|
|
|
333
408
|
def read_i32
|
|
334
|
-
zig_zag_to_int(read_varint32
|
|
409
|
+
zig_zag_to_int(read_varint32)
|
|
335
410
|
end
|
|
336
411
|
|
|
337
412
|
def read_i64
|
|
338
|
-
zig_zag_to_long(read_varint64
|
|
413
|
+
zig_zag_to_long(read_varint64 & 0xffffffffffffffff)
|
|
339
414
|
end
|
|
340
415
|
|
|
341
416
|
def read_double
|
|
342
417
|
trans.read_into_buffer(@rbuf, 8)
|
|
343
|
-
|
|
344
|
-
val
|
|
418
|
+
@rbuf.reverse.unpack1("G")
|
|
345
419
|
end
|
|
346
420
|
|
|
347
421
|
def read_string
|
|
@@ -350,16 +424,24 @@ module Thrift
|
|
|
350
424
|
end
|
|
351
425
|
|
|
352
426
|
def read_binary
|
|
353
|
-
size = read_varint32
|
|
427
|
+
size = read_varint32
|
|
428
|
+
if size > I32_MAX
|
|
429
|
+
raise ProtocolException.new(ProtocolException::SIZE_LIMIT, "Binary size limit exceeded")
|
|
430
|
+
end
|
|
431
|
+
check_string_size(size)
|
|
354
432
|
trans.read_all(size)
|
|
355
433
|
end
|
|
356
434
|
|
|
435
|
+
def skip_string
|
|
436
|
+
read_binary
|
|
437
|
+
end
|
|
438
|
+
|
|
357
439
|
def read_uuid
|
|
358
440
|
UUID.uuid_from_bytes(trans.read_all(16))
|
|
359
441
|
end
|
|
360
442
|
|
|
361
443
|
def to_s
|
|
362
|
-
"compact(#{super
|
|
444
|
+
"compact(#{super})"
|
|
363
445
|
end
|
|
364
446
|
|
|
365
447
|
private
|
|
@@ -369,60 +451,84 @@ module Thrift
|
|
|
369
451
|
# the wire differ only by the type indicator.
|
|
370
452
|
#
|
|
371
453
|
def write_collection_begin(elem_type, size)
|
|
454
|
+
size = validate_size(size)
|
|
455
|
+
compact_type = CompactTypes.get_compact_type(elem_type)
|
|
372
456
|
if size <= 14
|
|
373
|
-
|
|
457
|
+
write_byte_direct((size << 4) | compact_type)
|
|
374
458
|
else
|
|
375
|
-
|
|
459
|
+
write_byte_direct(0xf0 | compact_type)
|
|
376
460
|
write_varint32(size)
|
|
377
461
|
end
|
|
378
462
|
end
|
|
379
463
|
|
|
464
|
+
def write_byte_direct(byte)
|
|
465
|
+
@trans.write([byte].pack("C"))
|
|
466
|
+
end
|
|
467
|
+
|
|
380
468
|
def write_varint32(n)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
# i32buf[idx++] = (byte)n;
|
|
385
|
-
write_byte(n)
|
|
386
|
-
break
|
|
387
|
-
# return;
|
|
388
|
-
else
|
|
389
|
-
# i32buf[idx++] = (byte)((n & 0x7F) | 0x80);
|
|
390
|
-
write_byte((n & 0x7F) | 0x80)
|
|
391
|
-
n = n >> 7
|
|
392
|
-
end
|
|
469
|
+
if (n & ~0x7F) == 0
|
|
470
|
+
write_byte_direct(n)
|
|
471
|
+
return
|
|
393
472
|
end
|
|
394
|
-
|
|
473
|
+
|
|
474
|
+
buffer = String.new(capacity: MAX_VARINT32_BYTES, encoding: Encoding::BINARY)
|
|
475
|
+
while (n & ~0x7F) != 0
|
|
476
|
+
buffer << ((n & 0x7F) | 0x80)
|
|
477
|
+
n >>= 7
|
|
478
|
+
end
|
|
479
|
+
buffer << n
|
|
480
|
+
@trans.write(buffer)
|
|
395
481
|
end
|
|
396
482
|
|
|
397
483
|
SEVEN_BIT_MASK = 0x7F
|
|
398
484
|
EVERYTHING_ELSE_MASK = ~SEVEN_BIT_MASK
|
|
399
485
|
|
|
400
486
|
def write_varint64(n)
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
487
|
+
if (n & EVERYTHING_ELSE_MASK) == 0
|
|
488
|
+
write_byte_direct(n)
|
|
489
|
+
return
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
buffer = String.new(capacity: MAX_VARINT_BYTES, encoding: Encoding::BINARY)
|
|
493
|
+
while (n & EVERYTHING_ELSE_MASK) != 0
|
|
494
|
+
buffer << ((n & SEVEN_BIT_MASK) | 0x80)
|
|
495
|
+
n >>= 7
|
|
409
496
|
end
|
|
497
|
+
buffer << n
|
|
498
|
+
@trans.write(buffer)
|
|
410
499
|
end
|
|
411
500
|
|
|
412
|
-
def read_varint32
|
|
413
|
-
|
|
501
|
+
def read_varint32
|
|
502
|
+
shift = 0
|
|
503
|
+
result = 0
|
|
504
|
+
VARINT32_PREFIX_BYTES.times do
|
|
505
|
+
b = read_byte
|
|
506
|
+
result |= (b & 0x7f) << shift
|
|
507
|
+
return result if (b & 0x80) != 0x80
|
|
508
|
+
shift += 7
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
b = read_byte
|
|
512
|
+
if (b & 0x80) != 0
|
|
513
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Variable-length int over 5 bytes.")
|
|
514
|
+
end
|
|
515
|
+
if (b & ~MAX_VARINT32_LAST_BYTE) != 0
|
|
516
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Variable-length int overflows uint32.")
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
result | (b << shift)
|
|
414
520
|
end
|
|
415
521
|
|
|
416
|
-
def read_varint64
|
|
522
|
+
def read_varint64
|
|
417
523
|
shift = 0
|
|
418
524
|
result = 0
|
|
419
|
-
|
|
420
|
-
b = read_byte
|
|
525
|
+
MAX_VARINT_BYTES.times do
|
|
526
|
+
b = read_byte
|
|
421
527
|
result |= (b & 0x7f) << shift
|
|
422
|
-
|
|
528
|
+
return result if (b & 0x80) != 0x80
|
|
423
529
|
shift += 7
|
|
424
530
|
end
|
|
425
|
-
|
|
531
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Variable-length int over 10 bytes.")
|
|
426
532
|
end
|
|
427
533
|
|
|
428
534
|
def int_to_zig_zag(n)
|
|
@@ -443,11 +549,17 @@ module Thrift
|
|
|
443
549
|
end
|
|
444
550
|
|
|
445
551
|
def message_seqid_to_varint32(seqid)
|
|
446
|
-
|
|
447
|
-
|
|
552
|
+
seqid < 0 ? seqid + (2**32) : seqid
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def validate_size(size)
|
|
556
|
+
unless size.is_a?(Integer)
|
|
557
|
+
raise "nil argument not allowed!" if size.nil?
|
|
558
|
+
raise ::TypeError, "integer argument expected"
|
|
448
559
|
end
|
|
560
|
+
raise RangeError if size < 0 || size > I32_MAX
|
|
449
561
|
|
|
450
|
-
|
|
562
|
+
size
|
|
451
563
|
end
|
|
452
564
|
|
|
453
565
|
def message_seqid_from_varint32(seqid)
|
|
@@ -456,8 +568,12 @@ module Thrift
|
|
|
456
568
|
end
|
|
457
569
|
|
|
458
570
|
class CompactProtocolFactory < BaseProtocolFactory
|
|
571
|
+
def initialize(max_string_size: BaseProtocol::DEFAULT_MAX_STRING_SIZE)
|
|
572
|
+
@max_string_size = max_string_size
|
|
573
|
+
end
|
|
574
|
+
|
|
459
575
|
def get_protocol(trans)
|
|
460
|
-
CompactProtocol.new(trans)
|
|
576
|
+
CompactProtocol.new(trans, max_string_size: @max_string_size)
|
|
461
577
|
end
|
|
462
578
|
|
|
463
579
|
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
|
|
@@ -177,8 +178,9 @@ module Thrift
|
|
|
177
178
|
@header_transport.reset_protocol
|
|
178
179
|
reset_protocol_if_needed
|
|
179
180
|
rescue ProtocolException => ex
|
|
181
|
+
use_default_protocol
|
|
180
182
|
app_ex = ApplicationException.new(ApplicationException::INVALID_PROTOCOL, ex.message)
|
|
181
|
-
write_message_begin("", MessageTypes::EXCEPTION,
|
|
183
|
+
write_message_begin("", MessageTypes::EXCEPTION, @header_transport.sequence_id)
|
|
182
184
|
app_ex.write(self)
|
|
183
185
|
write_message_end
|
|
184
186
|
@header_transport.flush
|
|
@@ -263,12 +265,16 @@ module Thrift
|
|
|
263
265
|
@protocol.read_binary
|
|
264
266
|
end
|
|
265
267
|
|
|
268
|
+
def skip_string
|
|
269
|
+
@protocol.skip_string
|
|
270
|
+
end
|
|
271
|
+
|
|
266
272
|
def read_uuid
|
|
267
273
|
@protocol.read_uuid
|
|
268
274
|
end
|
|
269
275
|
|
|
270
276
|
def to_s
|
|
271
|
-
"header(#{@protocol
|
|
277
|
+
"header(#{@protocol})"
|
|
272
278
|
end
|
|
273
279
|
|
|
274
280
|
private
|
|
@@ -282,6 +288,12 @@ module Thrift
|
|
|
282
288
|
end
|
|
283
289
|
end
|
|
284
290
|
|
|
291
|
+
def use_default_protocol
|
|
292
|
+
@protocol = create_protocol(@default_protocol)
|
|
293
|
+
@current_protocol_id = @default_protocol
|
|
294
|
+
@header_transport.protocol_id = @default_protocol
|
|
295
|
+
end
|
|
296
|
+
|
|
285
297
|
# Creates a protocol instance based on protocol ID
|
|
286
298
|
def create_protocol(protocol_id)
|
|
287
299
|
case protocol_id
|
|
@@ -292,7 +304,7 @@ module Thrift
|
|
|
292
304
|
else
|
|
293
305
|
raise ProtocolException.new(
|
|
294
306
|
ProtocolException::INVALID_DATA,
|
|
295
|
-
"Unknown protocol ID: #{protocol_id}"
|
|
307
|
+
"Unknown protocol ID: #{protocol_id}",
|
|
296
308
|
)
|
|
297
309
|
end
|
|
298
310
|
end
|