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/ext/thrift_native.c
CHANGED
|
@@ -92,6 +92,7 @@ ID skip_method_id;
|
|
|
92
92
|
ID write_method_id;
|
|
93
93
|
ID read_all_method_id;
|
|
94
94
|
ID read_into_buffer_method_id;
|
|
95
|
+
ID reset_message_size_method_id;
|
|
95
96
|
ID force_binary_encoding_id;
|
|
96
97
|
ID convert_to_utf8_byte_buffer_id;
|
|
97
98
|
ID convert_to_string_id;
|
|
@@ -99,8 +100,10 @@ ID convert_to_string_id;
|
|
|
99
100
|
// constant ids
|
|
100
101
|
ID fields_const_id;
|
|
101
102
|
ID transport_ivar_id;
|
|
103
|
+
ID reset_message_size_ivar_id;
|
|
102
104
|
ID strict_read_ivar_id;
|
|
103
105
|
ID strict_write_ivar_id;
|
|
106
|
+
ID max_string_size_ivar_id;
|
|
104
107
|
|
|
105
108
|
// cached symbols
|
|
106
109
|
VALUE type_sym;
|
|
@@ -121,6 +124,7 @@ int PROTOERR_BAD_VERSION;
|
|
|
121
124
|
int PROTOERR_NOT_IMPLEMENTED;
|
|
122
125
|
int PROTOERR_DEPTH_LIMIT;
|
|
123
126
|
|
|
127
|
+
// cppcheck-suppress unusedFunction
|
|
124
128
|
RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
125
129
|
// cached classes
|
|
126
130
|
thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
|
|
@@ -199,6 +203,7 @@ RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
|
199
203
|
write_method_id = rb_intern("write");
|
|
200
204
|
read_all_method_id = rb_intern("read_all");
|
|
201
205
|
read_into_buffer_method_id = rb_intern("read_into_buffer");
|
|
206
|
+
reset_message_size_method_id = rb_intern("reset_message_size");
|
|
202
207
|
force_binary_encoding_id = rb_intern("force_binary_encoding");
|
|
203
208
|
convert_to_utf8_byte_buffer_id = rb_intern("convert_to_utf8_byte_buffer");
|
|
204
209
|
convert_to_string_id = rb_intern("convert_to_string");
|
|
@@ -206,8 +211,10 @@ RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
|
206
211
|
// constant ids
|
|
207
212
|
fields_const_id = rb_intern("FIELDS");
|
|
208
213
|
transport_ivar_id = rb_intern("@trans");
|
|
214
|
+
reset_message_size_ivar_id = rb_intern("@reset_message_size");
|
|
209
215
|
strict_read_ivar_id = rb_intern("@strict_read");
|
|
210
216
|
strict_write_ivar_id = rb_intern("@strict_write");
|
|
217
|
+
max_string_size_ivar_id = rb_intern("@max_string_size");
|
|
211
218
|
|
|
212
219
|
// cached symbols
|
|
213
220
|
type_sym = ID2SYM(rb_intern("type"));
|
data/lib/thrift/bytes.rb
CHANGED
|
@@ -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
|
|
@@ -28,21 +29,23 @@ module Thrift
|
|
|
28
29
|
# Returns a String with BINARY encoding, filled with null characters
|
|
29
30
|
# if size is greater than zero
|
|
30
31
|
def self.empty_byte_buffer(size = nil)
|
|
31
|
-
if
|
|
32
|
+
if size && size > 0
|
|
32
33
|
"\0".b * size
|
|
33
34
|
else
|
|
34
|
-
|
|
35
|
+
"".b
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# Forces the encoding of the buffer to BINARY. If the buffer
|
|
39
|
-
# passed is frozen, then it will be duplicated.
|
|
40
|
+
# passed is frozen and not already BINARY, then it will be duplicated.
|
|
40
41
|
#
|
|
41
42
|
# buffer - The String to force the encoding of.
|
|
42
43
|
#
|
|
43
44
|
# Returns the String passed with an encoding of BINARY; returned
|
|
44
45
|
# String may be a duplicate.
|
|
45
46
|
def self.force_binary_encoding(buffer)
|
|
47
|
+
return buffer if buffer.encoding == Encoding::BINARY
|
|
48
|
+
|
|
46
49
|
buffer = buffer.dup if buffer.frozen?
|
|
47
50
|
buffer.force_encoding(Encoding::BINARY)
|
|
48
51
|
end
|
data/lib/thrift/client.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
|
|
@@ -30,42 +31,22 @@ module Thrift
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def send_message(name, args_class, args = {})
|
|
33
|
-
|
|
34
|
-
@oprot.write_message_begin(name, MessageTypes::CALL, seqid)
|
|
35
|
-
send_message_args(args_class, args)
|
|
36
|
-
@pending_seqids << seqid
|
|
34
|
+
write_message(name, MessageTypes::CALL, args_class, args)
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
def send_oneway_message(name, args_class, args = {})
|
|
40
|
-
|
|
41
|
-
send_message_args(args_class, args)
|
|
38
|
+
write_message(name, MessageTypes::ONEWAY, args_class, args)
|
|
42
39
|
end
|
|
43
40
|
|
|
44
41
|
def send_message_args(args_class, args)
|
|
45
|
-
|
|
46
|
-
args.each do |k, v|
|
|
47
|
-
data.send("#{k.to_s}=", v)
|
|
48
|
-
end
|
|
49
|
-
begin
|
|
50
|
-
data.write(@oprot)
|
|
51
|
-
rescue StandardError => e
|
|
52
|
-
@oprot.trans.close
|
|
53
|
-
raise e
|
|
54
|
-
end
|
|
55
|
-
@oprot.write_message_end
|
|
56
|
-
@oprot.trans.flush
|
|
42
|
+
write_message(nil, nil, args_class, args)
|
|
57
43
|
end
|
|
58
44
|
|
|
59
|
-
def receive_message_begin
|
|
45
|
+
def receive_message_begin
|
|
60
46
|
fname, mtype, rseqid = @iprot.read_message_begin
|
|
61
47
|
[fname, mtype, rseqid]
|
|
62
48
|
end
|
|
63
49
|
|
|
64
|
-
def reply_seqid(rseqid)
|
|
65
|
-
expected_seqid = dequeue_pending_seqid
|
|
66
|
-
!expected_seqid.nil? && rseqid == expected_seqid
|
|
67
|
-
end
|
|
68
|
-
|
|
69
50
|
def validate_message_begin(fname, mtype, rseqid, expected_name)
|
|
70
51
|
expected_seqid = dequeue_pending_seqid
|
|
71
52
|
|
|
@@ -76,14 +57,14 @@ module Thrift
|
|
|
76
57
|
if mtype != MessageTypes::REPLY
|
|
77
58
|
raise ApplicationException.new(
|
|
78
59
|
ApplicationException::INVALID_MESSAGE_TYPE,
|
|
79
|
-
"#{expected_name} failed: invalid message type"
|
|
60
|
+
"#{expected_name} failed: invalid message type",
|
|
80
61
|
)
|
|
81
62
|
end
|
|
82
63
|
|
|
83
64
|
if fname != expected_name
|
|
84
65
|
raise ApplicationException.new(
|
|
85
66
|
ApplicationException::WRONG_METHOD_NAME,
|
|
86
|
-
"#{expected_name} failed: wrong method name"
|
|
67
|
+
"#{expected_name} failed: wrong method name",
|
|
87
68
|
)
|
|
88
69
|
end
|
|
89
70
|
|
|
@@ -91,7 +72,7 @@ module Thrift
|
|
|
91
72
|
|
|
92
73
|
raise ApplicationException.new(
|
|
93
74
|
ApplicationException::BAD_SEQUENCE_ID,
|
|
94
|
-
"#{expected_name} failed: out of sequence response"
|
|
75
|
+
"#{expected_name} failed: out of sequence response",
|
|
95
76
|
)
|
|
96
77
|
end
|
|
97
78
|
|
|
@@ -102,14 +83,31 @@ module Thrift
|
|
|
102
83
|
result
|
|
103
84
|
end
|
|
104
85
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def write_message(name, type, args_class, args)
|
|
89
|
+
data = args_class.new
|
|
90
|
+
args.each do |k, v|
|
|
91
|
+
data.send("#{k}=", v)
|
|
109
92
|
end
|
|
110
|
-
|
|
93
|
+
seqid = next_seqid! unless name.nil?
|
|
111
94
|
|
|
112
|
-
|
|
95
|
+
flush_result = begin
|
|
96
|
+
@oprot.write_message_begin(name, type, seqid) unless name.nil?
|
|
97
|
+
data.write(@oprot)
|
|
98
|
+
@oprot.write_message_end
|
|
99
|
+
@oprot.trans.flush
|
|
100
|
+
rescue StandardError
|
|
101
|
+
begin
|
|
102
|
+
@oprot.trans.close
|
|
103
|
+
rescue StandardError
|
|
104
|
+
# Preserve the original send error.
|
|
105
|
+
end
|
|
106
|
+
raise
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
type == MessageTypes::CALL ? @pending_seqids << seqid : flush_result
|
|
110
|
+
end
|
|
113
111
|
|
|
114
112
|
def next_seqid!
|
|
115
113
|
seqid = @seqid
|
data/lib/thrift/exceptions.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
|
|
@@ -18,6 +19,8 @@
|
|
|
18
19
|
#
|
|
19
20
|
|
|
20
21
|
module Thrift
|
|
22
|
+
DEFAULT_RECURSION_DEPTH = 64
|
|
23
|
+
|
|
21
24
|
class Exception < StandardError
|
|
22
25
|
def initialize(message)
|
|
23
26
|
super
|
|
@@ -28,7 +31,6 @@ module Thrift
|
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
class ApplicationException < Exception
|
|
31
|
-
|
|
32
34
|
UNKNOWN = 0
|
|
33
35
|
UNKNOWN_METHOD = 1
|
|
34
36
|
INVALID_MESSAGE_TYPE = 2
|
|
@@ -48,10 +50,11 @@ module Thrift
|
|
|
48
50
|
@type = type
|
|
49
51
|
end
|
|
50
52
|
|
|
51
|
-
def read(iprot)
|
|
53
|
+
def read(iprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
54
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
52
55
|
iprot.read_struct_begin
|
|
53
56
|
while true
|
|
54
|
-
|
|
57
|
+
_, ftype, fid = iprot.read_field_begin
|
|
55
58
|
if ftype == Types::STOP
|
|
56
59
|
break
|
|
57
60
|
end
|
|
@@ -67,21 +70,21 @@ module Thrift
|
|
|
67
70
|
iprot.read_struct_end
|
|
68
71
|
end
|
|
69
72
|
|
|
70
|
-
def write(oprot)
|
|
71
|
-
|
|
73
|
+
def write(oprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
|
|
74
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
|
|
75
|
+
oprot.write_struct_begin("Thrift::ApplicationException")
|
|
72
76
|
unless @message.nil?
|
|
73
|
-
oprot.write_field_begin(
|
|
77
|
+
oprot.write_field_begin("message", Types::STRING, 1)
|
|
74
78
|
oprot.write_string(@message)
|
|
75
79
|
oprot.write_field_end
|
|
76
80
|
end
|
|
77
81
|
unless @type.nil?
|
|
78
|
-
oprot.write_field_begin(
|
|
82
|
+
oprot.write_field_begin("type", Types::I32, 2)
|
|
79
83
|
oprot.write_i32(@type)
|
|
80
84
|
oprot.write_field_end
|
|
81
85
|
end
|
|
82
86
|
oprot.write_field_stop
|
|
83
87
|
oprot.write_struct_end
|
|
84
88
|
end
|
|
85
|
-
|
|
86
89
|
end
|
|
87
90
|
end
|
|
@@ -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,24 +17,33 @@
|
|
|
16
17
|
# specific language governing permissions and limitations
|
|
17
18
|
# under the License.
|
|
18
19
|
|
|
19
|
-
require
|
|
20
|
-
require
|
|
20
|
+
require "thrift/protocol/protocol_decorator"
|
|
21
|
+
require "thrift/protocol/base_protocol"
|
|
21
22
|
|
|
22
23
|
module Thrift
|
|
23
24
|
class MultiplexedProcessor
|
|
24
25
|
def initialize
|
|
25
26
|
@actual_processors = {}
|
|
27
|
+
@default_processor = nil
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def register_processor(service_name, processor)
|
|
29
31
|
@actual_processors[service_name] = processor
|
|
30
32
|
end
|
|
31
33
|
|
|
34
|
+
def register_default(processor)
|
|
35
|
+
@default_processor = processor
|
|
36
|
+
end
|
|
37
|
+
|
|
32
38
|
def process(iprot, oprot)
|
|
33
39
|
name, type, seqid = iprot.read_message_begin
|
|
34
40
|
check_type(type)
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
if name.count(":") < 1
|
|
42
|
+
check_default_processor(name)
|
|
43
|
+
return @default_processor.process(StoredMessageProtocol.new(iprot, [name, type, seqid]), oprot)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
service_name, method = name.split(":", 2)
|
|
37
47
|
processor(service_name).process(StoredMessageProtocol.new(iprot, [method, type, seqid]), oprot)
|
|
38
48
|
end
|
|
39
49
|
|
|
@@ -49,19 +59,18 @@ module Thrift
|
|
|
49
59
|
|
|
50
60
|
def check_type(type)
|
|
51
61
|
unless [MessageTypes::CALL, MessageTypes::ONEWAY].include?(type)
|
|
52
|
-
raise Thrift::Exception.new(
|
|
62
|
+
raise Thrift::Exception.new("This should not have happened!?")
|
|
53
63
|
end
|
|
54
64
|
end
|
|
55
65
|
|
|
56
|
-
def
|
|
57
|
-
|
|
66
|
+
def check_default_processor(name)
|
|
67
|
+
unless @default_processor
|
|
58
68
|
raise Thrift::Exception.new("Service name not found in message name: #{name}. Did you forget to use a Thrift::Protocol::MultiplexedProtocol in your client?")
|
|
59
69
|
end
|
|
60
70
|
end
|
|
61
71
|
end
|
|
62
72
|
|
|
63
73
|
class StoredMessageProtocol < BaseProtocol
|
|
64
|
-
|
|
65
74
|
include ProtocolDecorator
|
|
66
75
|
|
|
67
76
|
def initialize(protocol, message_begin)
|
data/lib/thrift/processor.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,10 +18,15 @@
|
|
|
17
18
|
# under the License.
|
|
18
19
|
#
|
|
19
20
|
|
|
20
|
-
require
|
|
21
|
+
require "logger"
|
|
22
|
+
require "thrift/protocol/base_protocol"
|
|
21
23
|
|
|
22
24
|
module Thrift
|
|
23
25
|
module Processor
|
|
26
|
+
class ArgumentProtocolException < ProtocolException
|
|
27
|
+
end
|
|
28
|
+
private_constant :ArgumentProtocolException
|
|
29
|
+
|
|
24
30
|
def initialize(handler, logger = nil)
|
|
25
31
|
@handler = handler
|
|
26
32
|
if logger.nil?
|
|
@@ -33,11 +39,25 @@ module Thrift
|
|
|
33
39
|
|
|
34
40
|
def process(iprot, oprot)
|
|
35
41
|
name, type, seqid = iprot.read_message_begin
|
|
42
|
+
unless type == MessageTypes::CALL || type == MessageTypes::ONEWAY
|
|
43
|
+
iprot.skip(Types::STRUCT)
|
|
44
|
+
iprot.read_message_end
|
|
45
|
+
x = ApplicationException.new(
|
|
46
|
+
ApplicationException::INVALID_MESSAGE_TYPE,
|
|
47
|
+
"Invalid message type #{type} for function #{name}",
|
|
48
|
+
)
|
|
49
|
+
write_error(x, oprot, name, seqid)
|
|
50
|
+
return false
|
|
51
|
+
end
|
|
52
|
+
|
|
36
53
|
if respond_to?("process_#{name}")
|
|
37
54
|
begin
|
|
38
55
|
send("process_#{name}", seqid, iprot, oprot)
|
|
56
|
+
rescue ArgumentProtocolException => e
|
|
57
|
+
x = ApplicationException.new(ApplicationException::PROTOCOL_ERROR, e.message)
|
|
58
|
+
write_error(x, oprot, name, seqid)
|
|
39
59
|
rescue => e
|
|
40
|
-
x = ApplicationException.new(ApplicationException::INTERNAL_ERROR,
|
|
60
|
+
x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, "Internal error")
|
|
41
61
|
@logger.debug "Internal error : #{e.message}\n#{e.backtrace.join("\n")}"
|
|
42
62
|
write_error(x, oprot, name, seqid)
|
|
43
63
|
end
|
|
@@ -45,7 +65,7 @@ module Thrift
|
|
|
45
65
|
else
|
|
46
66
|
iprot.skip(Types::STRUCT)
|
|
47
67
|
iprot.read_message_end
|
|
48
|
-
x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD,
|
|
68
|
+
x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD, "Unknown function " + name)
|
|
49
69
|
write_error(x, oprot, name, seqid)
|
|
50
70
|
false
|
|
51
71
|
end
|
|
@@ -56,6 +76,8 @@ module Thrift
|
|
|
56
76
|
args.read(iprot)
|
|
57
77
|
iprot.read_message_end
|
|
58
78
|
args
|
|
79
|
+
rescue ProtocolException => e
|
|
80
|
+
raise ArgumentProtocolException.new(e.type, e.message)
|
|
59
81
|
end
|
|
60
82
|
|
|
61
83
|
def write_result(result, oprot, name, seqid)
|
|
@@ -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
|
|
@@ -18,11 +19,11 @@
|
|
|
18
19
|
#
|
|
19
20
|
|
|
20
21
|
# this require is to make generated struct definitions happy
|
|
21
|
-
require
|
|
22
|
+
require "set"
|
|
23
|
+
require "thrift/exceptions"
|
|
22
24
|
|
|
23
25
|
module Thrift
|
|
24
26
|
class ProtocolException < Exception
|
|
25
|
-
|
|
26
27
|
UNKNOWN = 0
|
|
27
28
|
INVALID_DATA = 1
|
|
28
29
|
NEGATIVE_SIZE = 2
|
|
@@ -40,6 +41,14 @@ module Thrift
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
class BaseProtocol
|
|
44
|
+
MAX_CONTAINER_SIZE = (1 << 31) - 1
|
|
45
|
+
|
|
46
|
+
# The longest string or binary field BinaryProtocol and CompactProtocol read
|
|
47
|
+
# by default: the frame size limit the framed transports apply. A string's
|
|
48
|
+
# length is the read size handed to the transport, and an unframed transport
|
|
49
|
+
# has no frame to bound it. Pass max_string_size: nil to read strings of any
|
|
50
|
+
# length.
|
|
51
|
+
DEFAULT_MAX_STRING_SIZE = 16_384_000
|
|
43
52
|
|
|
44
53
|
attr_reader :trans
|
|
45
54
|
|
|
@@ -48,10 +57,24 @@ module Thrift
|
|
|
48
57
|
end
|
|
49
58
|
|
|
50
59
|
def native?
|
|
51
|
-
puts "wrong method is being called!"
|
|
52
60
|
false
|
|
53
61
|
end
|
|
54
62
|
|
|
63
|
+
# Raises a SIZE_LIMIT ProtocolException when a declared string length is over
|
|
64
|
+
# the protocol's max_string_size.
|
|
65
|
+
def check_string_size(size)
|
|
66
|
+
max = @max_string_size
|
|
67
|
+
return if max.nil? || size <= max
|
|
68
|
+
|
|
69
|
+
raise ProtocolException.new(ProtocolException::SIZE_LIMIT, "String size #{size} larger than the maximum #{max}")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.validate_max_string_size(max_string_size)
|
|
73
|
+
return if max_string_size.nil? || (max_string_size.is_a?(Integer) && max_string_size > 0)
|
|
74
|
+
|
|
75
|
+
raise ArgumentError, "max_string_size must be nil or a positive Integer"
|
|
76
|
+
end
|
|
77
|
+
|
|
55
78
|
def write_message_begin(name, type, seqid)
|
|
56
79
|
raise NotImplementedError
|
|
57
80
|
end
|
|
@@ -228,6 +251,10 @@ module Thrift
|
|
|
228
251
|
raise NotImplementedError
|
|
229
252
|
end
|
|
230
253
|
|
|
254
|
+
def skip_string
|
|
255
|
+
read_string
|
|
256
|
+
end
|
|
257
|
+
|
|
231
258
|
# Writes a field based on the field information, field ID and value.
|
|
232
259
|
#
|
|
233
260
|
# field_info - A Hash containing the definition of the field:
|
|
@@ -236,25 +263,19 @@ module Thrift
|
|
|
236
263
|
# :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
|
|
237
264
|
# fid - The ID of the field.
|
|
238
265
|
# value - The field's value to write; object type varies based on :type.
|
|
266
|
+
# remaining_depth - The optional recursion budget of the enclosing struct.
|
|
239
267
|
#
|
|
240
268
|
# Returns nothing.
|
|
241
|
-
def write_field(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
elsif args.size == 4
|
|
248
|
-
# handles the deprecated method signature - write_field(name, type, fid, value)
|
|
249
|
-
field_info = {:name => args[0], :type => args[1]}
|
|
250
|
-
fid = args[2]
|
|
251
|
-
value = args[3]
|
|
252
|
-
else
|
|
253
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for 3)"
|
|
269
|
+
def write_field(field_info, fid, value, remaining_depth = nil)
|
|
270
|
+
unless field_info.is_a?(Hash)
|
|
271
|
+
field_info = {name: field_info, type: fid}
|
|
272
|
+
fid = value
|
|
273
|
+
value = remaining_depth
|
|
274
|
+
remaining_depth = nil
|
|
254
275
|
end
|
|
255
276
|
|
|
256
277
|
write_field_begin(field_info[:name], field_info[:type], fid)
|
|
257
|
-
write_type(field_info, value)
|
|
278
|
+
write_type(field_info, value, remaining_depth)
|
|
258
279
|
write_field_end
|
|
259
280
|
end
|
|
260
281
|
|
|
@@ -264,13 +285,14 @@ module Thrift
|
|
|
264
285
|
# :type - The Thrift::Types constant that determines how the value is written.
|
|
265
286
|
# :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
|
|
266
287
|
# value - The field's value to write; object type varies based on field_info[:type].
|
|
288
|
+
# remaining_depth - The optional recursion budget of the enclosing struct.
|
|
267
289
|
#
|
|
268
290
|
# Returns nothing.
|
|
269
|
-
def write_type(field_info, value)
|
|
291
|
+
def write_type(field_info, value, remaining_depth = nil)
|
|
270
292
|
# if field_info is a Integer, assume it is a Thrift::Types constant
|
|
271
293
|
# convert it into a field_info Hash for backwards compatibility
|
|
272
294
|
if field_info.is_a? Integer
|
|
273
|
-
field_info = {:
|
|
295
|
+
field_info = {type: field_info}
|
|
274
296
|
end
|
|
275
297
|
|
|
276
298
|
case field_info[:type]
|
|
@@ -295,7 +317,11 @@ module Thrift
|
|
|
295
317
|
when Types::UUID
|
|
296
318
|
write_uuid(value)
|
|
297
319
|
when Types::STRUCT
|
|
298
|
-
|
|
320
|
+
if remaining_depth
|
|
321
|
+
value.write(self, remaining_depth - 1)
|
|
322
|
+
else
|
|
323
|
+
value.write(self)
|
|
324
|
+
end
|
|
299
325
|
else
|
|
300
326
|
raise NotImplementedError
|
|
301
327
|
end
|
|
@@ -312,7 +338,7 @@ module Thrift
|
|
|
312
338
|
# if field_info is a Integer, assume it is a Thrift::Types constant
|
|
313
339
|
# convert it into a field_info Hash for backwards compatibility
|
|
314
340
|
if field_info.is_a? Integer
|
|
315
|
-
field_info = {:
|
|
341
|
+
field_info = {type: field_info}
|
|
316
342
|
end
|
|
317
343
|
|
|
318
344
|
case field_info[:type]
|
|
@@ -341,7 +367,8 @@ module Thrift
|
|
|
341
367
|
end
|
|
342
368
|
end
|
|
343
369
|
|
|
344
|
-
def skip(type)
|
|
370
|
+
def skip(type, max_depth = 64)
|
|
371
|
+
raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum skip depth exceeded") if max_depth <= 0
|
|
345
372
|
case type
|
|
346
373
|
when Types::BOOL
|
|
347
374
|
read_bool
|
|
@@ -356,44 +383,52 @@ module Thrift
|
|
|
356
383
|
when Types::DOUBLE
|
|
357
384
|
read_double
|
|
358
385
|
when Types::STRING
|
|
359
|
-
|
|
386
|
+
skip_string
|
|
360
387
|
when Types::UUID
|
|
361
388
|
read_uuid
|
|
362
389
|
when Types::STRUCT
|
|
363
390
|
read_struct_begin
|
|
364
391
|
while true
|
|
365
|
-
|
|
392
|
+
_, type, _ = read_field_begin
|
|
366
393
|
break if type == Types::STOP
|
|
367
|
-
skip(type)
|
|
394
|
+
skip(type, max_depth - 1)
|
|
368
395
|
read_field_end
|
|
369
396
|
end
|
|
370
397
|
read_struct_end
|
|
371
398
|
when Types::MAP
|
|
372
399
|
ktype, vtype, size = read_map_begin
|
|
400
|
+
validate_container_size(size)
|
|
373
401
|
size.times do
|
|
374
|
-
skip(ktype)
|
|
375
|
-
skip(vtype)
|
|
402
|
+
skip(ktype, max_depth - 1)
|
|
403
|
+
skip(vtype, max_depth - 1)
|
|
376
404
|
end
|
|
377
405
|
read_map_end
|
|
378
406
|
when Types::SET
|
|
379
407
|
etype, size = read_set_begin
|
|
408
|
+
validate_container_size(size)
|
|
380
409
|
size.times do
|
|
381
|
-
skip(etype)
|
|
410
|
+
skip(etype, max_depth - 1)
|
|
382
411
|
end
|
|
383
412
|
read_set_end
|
|
384
413
|
when Types::LIST
|
|
385
414
|
etype, size = read_list_begin
|
|
415
|
+
validate_container_size(size)
|
|
386
416
|
size.times do
|
|
387
|
-
skip(etype)
|
|
417
|
+
skip(etype, max_depth - 1)
|
|
388
418
|
end
|
|
389
419
|
read_list_end
|
|
390
420
|
else
|
|
391
|
-
raise ProtocolException.new(ProtocolException::INVALID_DATA,
|
|
421
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Invalid data")
|
|
392
422
|
end
|
|
393
423
|
end
|
|
394
424
|
|
|
425
|
+
def validate_container_size(size)
|
|
426
|
+
raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, "Negative size") unless size >= 0
|
|
427
|
+
raise ProtocolException.new(ProtocolException::SIZE_LIMIT, "Container size limit exceeded") if size > MAX_CONTAINER_SIZE
|
|
428
|
+
end
|
|
429
|
+
|
|
395
430
|
def to_s
|
|
396
|
-
|
|
431
|
+
trans.to_s
|
|
397
432
|
end
|
|
398
433
|
end
|
|
399
434
|
|