thrift 0.22.0 → 0.23.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 +175 -17
- data/benchmark/benchmark.rb +22 -8
- data/benchmark/client.rb +49 -6
- data/benchmark/server.rb +45 -7
- data/benchmark/thin_server.rb +1 -0
- data/ext/binary_protocol_accelerated.c +76 -19
- data/ext/compact_protocol.c +80 -15
- data/ext/constants.h +12 -0
- data/ext/extconf.rb +10 -9
- data/ext/memory_buffer.c +7 -7
- data/ext/protocol.c +29 -0
- data/ext/protocol.h +35 -0
- data/ext/struct.c +36 -5
- data/ext/thrift_native.c +27 -3
- data/lib/thrift/bytes.rb +68 -101
- data/lib/thrift/client.rb +61 -9
- data/lib/thrift/exceptions.rb +5 -5
- data/lib/thrift/multiplexed_processor.rb +6 -6
- data/lib/thrift/processor.rb +6 -6
- data/lib/thrift/protocol/base_protocol.rb +37 -15
- data/lib/thrift/protocol/binary_protocol.rb +25 -9
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -5
- data/lib/thrift/protocol/compact_protocol.rb +61 -37
- data/lib/thrift/protocol/header_protocol.rb +320 -0
- data/lib/thrift/protocol/json_protocol.rb +26 -16
- data/lib/thrift/protocol/multiplexed_protocol.rb +5 -5
- data/lib/thrift/protocol/protocol_decorator.rb +12 -4
- data/lib/thrift/serializer/deserializer.rb +5 -5
- data/lib/thrift/serializer/serializer.rb +4 -5
- data/lib/thrift/server/base_server.rb +4 -4
- data/lib/thrift/server/mongrel_http_server.rb +6 -6
- data/lib/thrift/server/nonblocking_server.rb +8 -8
- data/lib/thrift/server/simple_server.rb +4 -4
- data/lib/thrift/server/thin_http_server.rb +3 -3
- data/lib/thrift/server/thread_pool_server.rb +6 -6
- data/lib/thrift/server/threaded_server.rb +4 -4
- data/lib/thrift/struct.rb +11 -11
- data/lib/thrift/struct_union.rb +19 -9
- data/lib/thrift/thrift_native.rb +1 -1
- data/lib/thrift/transport/base_server_transport.rb +5 -5
- data/lib/thrift/transport/base_transport.rb +12 -12
- data/lib/thrift/transport/buffered_transport.rb +6 -6
- data/lib/thrift/transport/framed_transport.rb +7 -7
- data/lib/thrift/transport/header_transport.rb +516 -0
- data/lib/thrift/transport/http_client_transport.rb +1 -1
- data/lib/thrift/transport/io_stream_transport.rb +3 -3
- data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
- data/lib/thrift/transport/server_socket.rb +8 -5
- data/lib/thrift/transport/socket.rb +58 -31
- data/lib/thrift/transport/ssl_server_socket.rb +1 -1
- data/lib/thrift/transport/ssl_socket.rb +2 -2
- data/lib/thrift/transport/unix_server_socket.rb +4 -4
- data/lib/thrift/transport/unix_socket.rb +6 -6
- data/lib/thrift/types.rb +9 -6
- data/lib/thrift/union.rb +14 -8
- data/lib/thrift/uuid.rb +49 -0
- data/lib/thrift.rb +3 -1
- data/spec/ThriftSpec.thrift +5 -1
- data/spec/base_protocol_spec.rb +1 -2
- data/spec/base_transport_spec.rb +6 -7
- data/spec/binary_protocol_spec.rb +0 -2
- data/spec/binary_protocol_spec_shared.rb +129 -142
- data/spec/bytes_spec.rb +57 -118
- data/spec/client_spec.rb +85 -19
- data/spec/compact_protocol_spec.rb +54 -16
- data/spec/constants_demo_spec.rb +101 -0
- data/spec/exception_spec.rb +0 -1
- data/spec/header_protocol_spec.rb +475 -0
- data/spec/header_transport_spec.rb +386 -0
- data/spec/http_client_spec.rb +4 -6
- data/spec/json_protocol_spec.rb +47 -47
- data/spec/namespaced_spec.rb +0 -1
- data/spec/nonblocking_server_spec.rb +102 -4
- data/spec/processor_spec.rb +0 -1
- data/spec/serializer_spec.rb +0 -1
- data/spec/server_socket_spec.rb +1 -1
- data/spec/server_spec.rb +8 -9
- data/spec/socket_spec.rb +0 -1
- data/spec/socket_spec_shared.rb +72 -9
- data/spec/spec_helper.rb +1 -1
- data/spec/ssl_server_socket_spec.rb +12 -1
- data/spec/ssl_socket_spec.rb +10 -1
- data/spec/struct_nested_containers_spec.rb +1 -2
- data/spec/struct_spec.rb +113 -9
- data/spec/support/header_protocol_helper.rb +54 -0
- data/spec/thin_http_server_spec.rb +3 -18
- data/spec/types_spec.rb +25 -26
- data/spec/union_spec.rb +69 -11
- data/spec/unix_socket_spec.rb +1 -2
- data/spec/uuid_validation_spec.rb +238 -0
- data/test/fuzz/Makefile.am +173 -0
- data/test/fuzz/README.md +149 -0
- data/test/fuzz/fuzz_common.rb +95 -0
- data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +3 -4
- data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +6 -13
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +22 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +22 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_tracer.rb +28 -0
- metadata +106 -37
data/ext/struct.c
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
#include "struct.h"
|
|
21
21
|
#include "constants.h"
|
|
22
22
|
#include "macros.h"
|
|
23
|
+
#include "protocol.h"
|
|
23
24
|
#include "strlcpy.h"
|
|
24
25
|
|
|
25
26
|
VALUE thrift_union_class;
|
|
@@ -34,6 +35,19 @@ static ID sorted_field_ids_method_id;
|
|
|
34
35
|
#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
|
|
35
36
|
#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
|
|
36
37
|
|
|
38
|
+
static VALUE new_container_array(int size) {
|
|
39
|
+
if (size < 0) {
|
|
40
|
+
rb_exc_raise(
|
|
41
|
+
get_protocol_exception(
|
|
42
|
+
INT2FIX(PROTOERR_NEGATIVE_SIZE),
|
|
43
|
+
rb_str_new2("Negative container size")
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return rb_ary_new2(size > 1024 ? 1024 : size);
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
//-------------------------------------------
|
|
38
52
|
// Writing section
|
|
39
53
|
//-------------------------------------------
|
|
@@ -75,6 +89,11 @@ VALUE default_write_string(VALUE protocol, VALUE value) {
|
|
|
75
89
|
return Qnil;
|
|
76
90
|
}
|
|
77
91
|
|
|
92
|
+
VALUE default_write_uuid(VALUE protocol, VALUE value) {
|
|
93
|
+
rb_funcall(protocol, write_uuid_method_id, 1, value);
|
|
94
|
+
return Qnil;
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
VALUE default_write_binary(VALUE protocol, VALUE value) {
|
|
79
98
|
rb_funcall(protocol, write_binary_method_id, 1, value);
|
|
80
99
|
return Qnil;
|
|
@@ -195,6 +214,10 @@ VALUE default_read_string(VALUE protocol) {
|
|
|
195
214
|
return rb_funcall(protocol, read_string_method_id, 0);
|
|
196
215
|
}
|
|
197
216
|
|
|
217
|
+
VALUE default_read_uuid(VALUE protocol) {
|
|
218
|
+
return rb_funcall(protocol, read_uuid_method_id, 0);
|
|
219
|
+
}
|
|
220
|
+
|
|
198
221
|
VALUE default_read_binary(VALUE protocol) {
|
|
199
222
|
return rb_funcall(protocol, read_binary_method_id, 0);
|
|
200
223
|
}
|
|
@@ -342,6 +365,8 @@ static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_i
|
|
|
342
365
|
} else {
|
|
343
366
|
default_write_binary(protocol, value);
|
|
344
367
|
}
|
|
368
|
+
} else if (ttype == TTYPE_UUID) {
|
|
369
|
+
default_write_uuid(protocol, value);
|
|
345
370
|
} else if (IS_CONTAINER(ttype)) {
|
|
346
371
|
write_container(ttype, field_info, value, protocol);
|
|
347
372
|
} else if (ttype == TTYPE_STRUCT) {
|
|
@@ -452,6 +477,8 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
452
477
|
}
|
|
453
478
|
} else if (ttype == TTYPE_DOUBLE) {
|
|
454
479
|
result = default_read_double(protocol);
|
|
480
|
+
} else if (ttype == TTYPE_UUID) {
|
|
481
|
+
result = default_read_uuid(protocol);
|
|
455
482
|
} else if (ttype == TTYPE_STRUCT) {
|
|
456
483
|
VALUE klass = rb_hash_aref(field_info, class_sym);
|
|
457
484
|
result = rb_class_new_instance(0, NULL, klass);
|
|
@@ -469,6 +496,10 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
469
496
|
int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
|
|
470
497
|
int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
|
|
471
498
|
|
|
499
|
+
if (num_entries < 0) {
|
|
500
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_NEGATIVE_SIZE), rb_str_new2("Negative container size")));
|
|
501
|
+
}
|
|
502
|
+
|
|
472
503
|
// Check the declared key and value types against the expected ones and skip the map contents
|
|
473
504
|
// if the types don't match.
|
|
474
505
|
VALUE key_info = rb_hash_aref(field_info, key_sym);
|
|
@@ -509,7 +540,7 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
509
540
|
if (!NIL_P(element_info)) {
|
|
510
541
|
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
|
511
542
|
if (specified_element_type == element_ttype) {
|
|
512
|
-
result =
|
|
543
|
+
result = new_container_array(num_elements);
|
|
513
544
|
|
|
514
545
|
for (i = 0; i < num_elements; ++i) {
|
|
515
546
|
rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
@@ -536,7 +567,7 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
536
567
|
if (!NIL_P(element_info)) {
|
|
537
568
|
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
|
538
569
|
if (specified_element_type == element_ttype) {
|
|
539
|
-
items =
|
|
570
|
+
items = new_container_array(num_elements);
|
|
540
571
|
|
|
541
572
|
for (i = 0; i < num_elements; ++i) {
|
|
542
573
|
rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
@@ -643,7 +674,7 @@ static VALUE rb_thrift_union_read(VALUE self, VALUE protocol) {
|
|
|
643
674
|
field_type = FIX2INT(field_type_value);
|
|
644
675
|
|
|
645
676
|
if (field_type != TTYPE_STOP) {
|
|
646
|
-
|
|
677
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("too many fields in union!")));
|
|
647
678
|
}
|
|
648
679
|
|
|
649
680
|
// read struct end
|
|
@@ -671,7 +702,7 @@ static VALUE rb_thrift_union_write(VALUE self, VALUE protocol) {
|
|
|
671
702
|
VALUE field_info = rb_hash_aref(struct_fields, field_id);
|
|
672
703
|
|
|
673
704
|
if(NIL_P(field_info)) {
|
|
674
|
-
|
|
705
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("set_field is not valid for this union!")));
|
|
675
706
|
}
|
|
676
707
|
|
|
677
708
|
VALUE ttype_value = rb_hash_aref(field_info, type_sym);
|
|
@@ -691,7 +722,7 @@ static VALUE rb_thrift_union_write(VALUE self, VALUE protocol) {
|
|
|
691
722
|
return Qnil;
|
|
692
723
|
}
|
|
693
724
|
|
|
694
|
-
void Init_struct() {
|
|
725
|
+
void Init_struct(void) {
|
|
695
726
|
VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct"));
|
|
696
727
|
|
|
697
728
|
rb_define_method(struct_module, "write", rb_thrift_struct_write, 1);
|
data/ext/thrift_native.c
CHANGED
|
@@ -43,6 +43,7 @@ int TTYPE_MAP;
|
|
|
43
43
|
int TTYPE_SET;
|
|
44
44
|
int TTYPE_LIST;
|
|
45
45
|
int TTYPE_STRUCT;
|
|
46
|
+
int TTYPE_UUID;
|
|
46
47
|
|
|
47
48
|
// method ids
|
|
48
49
|
ID validate_method_id;
|
|
@@ -57,6 +58,7 @@ ID write_i32_method_id;
|
|
|
57
58
|
ID write_i64_method_id;
|
|
58
59
|
ID write_double_method_id;
|
|
59
60
|
ID write_string_method_id;
|
|
61
|
+
ID write_uuid_method_id;
|
|
60
62
|
ID write_binary_method_id;
|
|
61
63
|
ID write_map_begin_method_id;
|
|
62
64
|
ID write_map_end_method_id;
|
|
@@ -70,6 +72,7 @@ ID read_i16_method_id;
|
|
|
70
72
|
ID read_i32_method_id;
|
|
71
73
|
ID read_i64_method_id;
|
|
72
74
|
ID read_string_method_id;
|
|
75
|
+
ID read_uuid_method_id;
|
|
73
76
|
ID read_binary_method_id;
|
|
74
77
|
ID read_double_method_id;
|
|
75
78
|
ID read_map_begin_method_id;
|
|
@@ -109,7 +112,16 @@ VALUE class_sym;
|
|
|
109
112
|
VALUE binary_sym;
|
|
110
113
|
VALUE protocol_exception_class;
|
|
111
114
|
|
|
112
|
-
|
|
115
|
+
// protocol errors
|
|
116
|
+
int PROTOERR_UNKNOWN;
|
|
117
|
+
int PROTOERR_INVALID_DATA;
|
|
118
|
+
int PROTOERR_NEGATIVE_SIZE;
|
|
119
|
+
int PROTOERR_SIZE_LIMIT;
|
|
120
|
+
int PROTOERR_BAD_VERSION;
|
|
121
|
+
int PROTOERR_NOT_IMPLEMENTED;
|
|
122
|
+
int PROTOERR_DEPTH_LIMIT;
|
|
123
|
+
|
|
124
|
+
RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
113
125
|
// cached classes
|
|
114
126
|
thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
|
|
115
127
|
rb_global_variable(&thrift_module);
|
|
@@ -138,6 +150,7 @@ void Init_thrift_native() {
|
|
|
138
150
|
TTYPE_SET = FIX2INT(rb_const_get(thrift_types_module, rb_intern("SET")));
|
|
139
151
|
TTYPE_LIST = FIX2INT(rb_const_get(thrift_types_module, rb_intern("LIST")));
|
|
140
152
|
TTYPE_STRUCT = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRUCT")));
|
|
153
|
+
TTYPE_UUID = FIX2INT(rb_const_get(thrift_types_module, rb_intern("UUID")));
|
|
141
154
|
|
|
142
155
|
// method ids
|
|
143
156
|
validate_method_id = rb_intern("validate");
|
|
@@ -152,6 +165,7 @@ void Init_thrift_native() {
|
|
|
152
165
|
write_i64_method_id = rb_intern("write_i64");
|
|
153
166
|
write_double_method_id = rb_intern("write_double");
|
|
154
167
|
write_string_method_id = rb_intern("write_string");
|
|
168
|
+
write_uuid_method_id = rb_intern("write_uuid");
|
|
155
169
|
write_binary_method_id = rb_intern("write_binary");
|
|
156
170
|
write_map_begin_method_id = rb_intern("write_map_begin");
|
|
157
171
|
write_map_end_method_id = rb_intern("write_map_end");
|
|
@@ -165,10 +179,11 @@ void Init_thrift_native() {
|
|
|
165
179
|
read_i32_method_id = rb_intern("read_i32");
|
|
166
180
|
read_i64_method_id = rb_intern("read_i64");
|
|
167
181
|
read_string_method_id = rb_intern("read_string");
|
|
182
|
+
read_uuid_method_id = rb_intern("read_uuid");
|
|
168
183
|
read_binary_method_id = rb_intern("read_binary");
|
|
169
184
|
read_double_method_id = rb_intern("read_double");
|
|
170
185
|
read_map_begin_method_id = rb_intern("read_map_begin");
|
|
171
|
-
read_map_end_method_id = rb_intern("read_map_end");
|
|
186
|
+
read_map_end_method_id = rb_intern("read_map_end");
|
|
172
187
|
read_list_begin_method_id = rb_intern("read_list_begin");
|
|
173
188
|
read_list_end_method_id = rb_intern("read_list_end");
|
|
174
189
|
read_set_begin_method_id = rb_intern("read_set_begin");
|
|
@@ -192,7 +207,7 @@ void Init_thrift_native() {
|
|
|
192
207
|
fields_const_id = rb_intern("FIELDS");
|
|
193
208
|
transport_ivar_id = rb_intern("@trans");
|
|
194
209
|
strict_read_ivar_id = rb_intern("@strict_read");
|
|
195
|
-
strict_write_ivar_id = rb_intern("@strict_write");
|
|
210
|
+
strict_write_ivar_id = rb_intern("@strict_write");
|
|
196
211
|
|
|
197
212
|
// cached symbols
|
|
198
213
|
type_sym = ID2SYM(rb_intern("type"));
|
|
@@ -203,6 +218,15 @@ void Init_thrift_native() {
|
|
|
203
218
|
class_sym = ID2SYM(rb_intern("class"));
|
|
204
219
|
binary_sym = ID2SYM(rb_intern("binary"));
|
|
205
220
|
|
|
221
|
+
// protocol errors
|
|
222
|
+
PROTOERR_UNKNOWN = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("UNKNOWN")));
|
|
223
|
+
PROTOERR_INVALID_DATA = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("INVALID_DATA")));
|
|
224
|
+
PROTOERR_NEGATIVE_SIZE = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("NEGATIVE_SIZE")));
|
|
225
|
+
PROTOERR_SIZE_LIMIT = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("SIZE_LIMIT")));
|
|
226
|
+
PROTOERR_BAD_VERSION = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("BAD_VERSION")));
|
|
227
|
+
PROTOERR_NOT_IMPLEMENTED = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("NOT_IMPLEMENTED")));
|
|
228
|
+
PROTOERR_DEPTH_LIMIT = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("DEPTH_LIMIT")));
|
|
229
|
+
|
|
206
230
|
rb_global_variable(&type_sym);
|
|
207
231
|
rb_global_variable(&name_sym);
|
|
208
232
|
rb_global_variable(&key_sym);
|
data/lib/thrift/bytes.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
4
|
# or more contributor license agreements. See the NOTICE file
|
|
5
5
|
# distributed with this work for additional information
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
# to you under the Apache License, Version 2.0 (the
|
|
8
8
|
# "License"); you may not use this file except in compliance
|
|
9
9
|
# with the License. You may obtain a copy of the License at
|
|
10
|
-
#
|
|
10
|
+
#
|
|
11
11
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
#
|
|
12
|
+
#
|
|
13
13
|
# Unless required by applicable law or agreed to in writing,
|
|
14
14
|
# software distributed under the License is distributed on an
|
|
15
15
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
@@ -21,111 +21,78 @@
|
|
|
21
21
|
module Thrift
|
|
22
22
|
# A collection of utilities for working with bytes and byte buffers.
|
|
23
23
|
module Bytes
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
''.force_encoding(Encoding::BINARY)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# Forces the encoding of the buffer to BINARY. If the buffer
|
|
40
|
-
# passed is frozen, then it will be duplicated.
|
|
41
|
-
#
|
|
42
|
-
# buffer - The String to force the encoding of.
|
|
43
|
-
#
|
|
44
|
-
# Returns the String passed with an encoding of BINARY; returned
|
|
45
|
-
# String may be a duplicate.
|
|
46
|
-
def self.force_binary_encoding(buffer)
|
|
47
|
-
buffer = buffer.dup if buffer.frozen?
|
|
48
|
-
buffer.force_encoding(Encoding::BINARY)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Gets the byte value of a given position in a String.
|
|
52
|
-
#
|
|
53
|
-
# string - The String to retrive the byte value from.
|
|
54
|
-
# index - The Integer location of the byte value to retrieve.
|
|
55
|
-
#
|
|
56
|
-
# Returns an Integer value between 0 and 255.
|
|
57
|
-
def self.get_string_byte(string, index)
|
|
58
|
-
string.getbyte(index)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Sets the byte value given to a given index in a String.
|
|
62
|
-
#
|
|
63
|
-
# string - The String to set the byte value in.
|
|
64
|
-
# index - The Integer location to set the byte value at.
|
|
65
|
-
# byte - The Integer value (0 to 255) to set in the string.
|
|
66
|
-
#
|
|
67
|
-
# Returns an Integer value of the byte value to set.
|
|
68
|
-
def self.set_string_byte(string, index, byte)
|
|
69
|
-
string.setbyte(index, byte)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Converts the given String to a UTF-8 byte buffer.
|
|
73
|
-
#
|
|
74
|
-
# string - The String to convert.
|
|
75
|
-
#
|
|
76
|
-
# Returns a new String with BINARY encoding, containing the UTF-8
|
|
77
|
-
# bytes of the original string.
|
|
78
|
-
def self.convert_to_utf8_byte_buffer(string)
|
|
79
|
-
if string.encoding != Encoding::UTF_8
|
|
80
|
-
# transcode to UTF-8
|
|
81
|
-
string = string.encode(Encoding::UTF_8)
|
|
82
|
-
else
|
|
83
|
-
# encoding is already UTF-8, but a duplicate is needed
|
|
84
|
-
string = string.dup
|
|
85
|
-
end
|
|
86
|
-
string.force_encoding(Encoding::BINARY)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Converts the given UTF-8 byte buffer into a String
|
|
90
|
-
#
|
|
91
|
-
# utf8_buffer - A String, with BINARY encoding, containing UTF-8 bytes
|
|
92
|
-
#
|
|
93
|
-
# Returns a new String with UTF-8 encoding,
|
|
94
|
-
def self.convert_to_string(utf8_buffer)
|
|
95
|
-
# duplicate the buffer, force encoding to UTF-8
|
|
96
|
-
utf8_buffer.dup.force_encoding(Encoding::UTF_8)
|
|
97
|
-
end
|
|
98
|
-
else
|
|
99
|
-
def self.empty_byte_buffer(size = nil)
|
|
100
|
-
if (size && size > 0)
|
|
101
|
-
"\0" * size
|
|
102
|
-
else
|
|
103
|
-
''
|
|
104
|
-
end
|
|
24
|
+
# Creates and empty byte buffer (String with BINARY encoding)
|
|
25
|
+
#
|
|
26
|
+
# size - The Integer size of the buffer (default: nil) to create
|
|
27
|
+
#
|
|
28
|
+
# Returns a String with BINARY encoding, filled with null characters
|
|
29
|
+
# if size is greater than zero
|
|
30
|
+
def self.empty_byte_buffer(size = nil)
|
|
31
|
+
if (size && size > 0)
|
|
32
|
+
"\0".b * size
|
|
33
|
+
else
|
|
34
|
+
''.b
|
|
105
35
|
end
|
|
36
|
+
end
|
|
106
37
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
38
|
+
# Forces the encoding of the buffer to BINARY. If the buffer
|
|
39
|
+
# passed is frozen, then it will be duplicated.
|
|
40
|
+
#
|
|
41
|
+
# buffer - The String to force the encoding of.
|
|
42
|
+
#
|
|
43
|
+
# Returns the String passed with an encoding of BINARY; returned
|
|
44
|
+
# String may be a duplicate.
|
|
45
|
+
def self.force_binary_encoding(buffer)
|
|
46
|
+
buffer = buffer.dup if buffer.frozen?
|
|
47
|
+
buffer.force_encoding(Encoding::BINARY)
|
|
48
|
+
end
|
|
110
49
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
50
|
+
# Gets the byte value of a given position in a String.
|
|
51
|
+
#
|
|
52
|
+
# string - The String to retrive the byte value from.
|
|
53
|
+
# index - The Integer location of the byte value to retrieve.
|
|
54
|
+
#
|
|
55
|
+
# Returns an Integer value between 0 and 255.
|
|
56
|
+
def self.get_string_byte(string, index)
|
|
57
|
+
string.getbyte(index)
|
|
58
|
+
end
|
|
114
59
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
60
|
+
# Sets the byte value given to a given index in a String.
|
|
61
|
+
#
|
|
62
|
+
# string - The String to set the byte value in.
|
|
63
|
+
# index - The Integer location to set the byte value at.
|
|
64
|
+
# byte - The Integer value (0 to 255) to set in the string.
|
|
65
|
+
#
|
|
66
|
+
# Returns an Integer value of the byte value to set.
|
|
67
|
+
def self.set_string_byte(string, index, byte)
|
|
68
|
+
string.setbyte(index, byte)
|
|
69
|
+
end
|
|
118
70
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
71
|
+
# Converts the given String to a UTF-8 byte buffer.
|
|
72
|
+
#
|
|
73
|
+
# string - The String to convert.
|
|
74
|
+
#
|
|
75
|
+
# Returns a new String with BINARY encoding, containing the UTF-8
|
|
76
|
+
# bytes of the original string.
|
|
77
|
+
def self.convert_to_utf8_byte_buffer(string)
|
|
78
|
+
if string.encoding != Encoding::UTF_8
|
|
79
|
+
# transcode to UTF-8
|
|
80
|
+
string = string.encode(Encoding::UTF_8)
|
|
81
|
+
else
|
|
82
|
+
# encoding is already UTF-8, but a duplicate is needed
|
|
83
|
+
string = string.dup
|
|
123
84
|
end
|
|
85
|
+
string.force_encoding(Encoding::BINARY)
|
|
86
|
+
end
|
|
124
87
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
88
|
+
# Converts the given UTF-8 byte buffer into a String
|
|
89
|
+
#
|
|
90
|
+
# utf8_buffer - A String, with BINARY encoding, containing UTF-8 bytes
|
|
91
|
+
#
|
|
92
|
+
# Returns a new String with UTF-8 encoding,
|
|
93
|
+
def self.convert_to_string(utf8_buffer)
|
|
94
|
+
# duplicate the buffer, force encoding to UTF-8
|
|
95
|
+
utf8_buffer.dup.force_encoding(Encoding::UTF_8)
|
|
129
96
|
end
|
|
130
97
|
end
|
|
131
98
|
end
|
data/lib/thrift/client.rb
CHANGED
|
@@ -19,19 +19,25 @@
|
|
|
19
19
|
|
|
20
20
|
module Thrift
|
|
21
21
|
module Client
|
|
22
|
-
|
|
22
|
+
MIN_SEQUENCE_ID = -(2**31)
|
|
23
|
+
MAX_SEQUENCE_ID = (2**31) - 1
|
|
24
|
+
|
|
25
|
+
def initialize(iprot, oprot = nil)
|
|
23
26
|
@iprot = iprot
|
|
24
27
|
@oprot = oprot || iprot
|
|
25
28
|
@seqid = 0
|
|
29
|
+
@pending_seqids = []
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
def send_message(name, args_class, args = {})
|
|
29
|
-
|
|
33
|
+
seqid = next_seqid!
|
|
34
|
+
@oprot.write_message_begin(name, MessageTypes::CALL, seqid)
|
|
30
35
|
send_message_args(args_class, args)
|
|
36
|
+
@pending_seqids << seqid
|
|
31
37
|
end
|
|
32
38
|
|
|
33
39
|
def send_oneway_message(name, args_class, args = {})
|
|
34
|
-
@oprot.write_message_begin(name, MessageTypes::ONEWAY,
|
|
40
|
+
@oprot.write_message_begin(name, MessageTypes::ONEWAY, next_seqid!)
|
|
35
41
|
send_message_args(args_class, args)
|
|
36
42
|
end
|
|
37
43
|
|
|
@@ -56,8 +62,37 @@ module Thrift
|
|
|
56
62
|
end
|
|
57
63
|
|
|
58
64
|
def reply_seqid(rseqid)
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
expected_seqid = dequeue_pending_seqid
|
|
66
|
+
!expected_seqid.nil? && rseqid == expected_seqid
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def validate_message_begin(fname, mtype, rseqid, expected_name)
|
|
70
|
+
expected_seqid = dequeue_pending_seqid
|
|
71
|
+
|
|
72
|
+
if mtype == MessageTypes::EXCEPTION
|
|
73
|
+
raise_application_exception
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if mtype != MessageTypes::REPLY
|
|
77
|
+
raise ApplicationException.new(
|
|
78
|
+
ApplicationException::INVALID_MESSAGE_TYPE,
|
|
79
|
+
"#{expected_name} failed: invalid message type"
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
if fname != expected_name
|
|
84
|
+
raise ApplicationException.new(
|
|
85
|
+
ApplicationException::WRONG_METHOD_NAME,
|
|
86
|
+
"#{expected_name} failed: wrong method name"
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
return if !expected_seqid.nil? && rseqid == expected_seqid
|
|
91
|
+
|
|
92
|
+
raise ApplicationException.new(
|
|
93
|
+
ApplicationException::BAD_SEQUENCE_ID,
|
|
94
|
+
"#{expected_name} failed: out of sequence response"
|
|
95
|
+
)
|
|
61
96
|
end
|
|
62
97
|
|
|
63
98
|
def receive_message(result_klass)
|
|
@@ -69,11 +104,28 @@ module Thrift
|
|
|
69
104
|
|
|
70
105
|
def handle_exception(mtype)
|
|
71
106
|
if mtype == MessageTypes::EXCEPTION
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@iprot.read_message_end
|
|
75
|
-
raise x
|
|
107
|
+
dequeue_pending_seqid
|
|
108
|
+
raise_application_exception
|
|
76
109
|
end
|
|
77
110
|
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
def next_seqid!
|
|
115
|
+
seqid = @seqid
|
|
116
|
+
@seqid = (seqid == MAX_SEQUENCE_ID) ? MIN_SEQUENCE_ID : seqid + 1
|
|
117
|
+
seqid
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def dequeue_pending_seqid
|
|
121
|
+
@pending_seqids.shift
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def raise_application_exception
|
|
125
|
+
x = ApplicationException.new
|
|
126
|
+
x.read(@iprot)
|
|
127
|
+
@iprot.read_message_end
|
|
128
|
+
raise x
|
|
129
|
+
end
|
|
78
130
|
end
|
|
79
131
|
end
|
data/lib/thrift/exceptions.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
#
|
|
2
2
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
3
|
# or more contributor license agreements. See the NOTICE file
|
|
4
4
|
# distributed with this work for additional information
|
|
@@ -6,16 +6,16 @@
|
|
|
6
6
|
# to you under the Apache License, Version 2.0 (the
|
|
7
7
|
# "License"); you may not use this file except in compliance
|
|
8
8
|
# with the License. You may obtain a copy of the License at
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
11
|
+
#
|
|
12
12
|
# Unless required by applicable law or agreed to in writing,
|
|
13
13
|
# software distributed under the License is distributed on an
|
|
14
14
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
15
|
# KIND, either express or implied. See the License for the
|
|
16
16
|
# specific language governing permissions and limitations
|
|
17
17
|
# under the License.
|
|
18
|
-
#
|
|
18
|
+
#
|
|
19
19
|
|
|
20
20
|
module Thrift
|
|
21
21
|
class Exception < StandardError
|
|
@@ -43,7 +43,7 @@ module Thrift
|
|
|
43
43
|
|
|
44
44
|
attr_reader :type
|
|
45
45
|
|
|
46
|
-
def initialize(type=UNKNOWN, message=nil)
|
|
46
|
+
def initialize(type = UNKNOWN, message = nil)
|
|
47
47
|
super(message)
|
|
48
48
|
@type = type
|
|
49
49
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
#
|
|
2
2
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
3
|
# or more contributor license agreements. See the NOTICE file
|
|
4
4
|
# distributed with this work for additional information
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
# to you under the Apache License, Version 2.0 (the
|
|
7
7
|
# "License"); you may not use this file except in compliance
|
|
8
8
|
# with the License. You may obtain a copy of the License at
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
11
|
+
#
|
|
12
12
|
# Unless required by applicable law or agreed to in writing,
|
|
13
13
|
# software distributed under the License is distributed on an
|
|
14
14
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
@@ -24,11 +24,11 @@ module Thrift
|
|
|
24
24
|
def initialize
|
|
25
25
|
@actual_processors = {}
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
def register_processor(service_name, processor)
|
|
29
29
|
@actual_processors[service_name] = processor
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
def process(iprot, oprot)
|
|
33
33
|
name, type, seqid = iprot.read_message_begin
|
|
34
34
|
check_type(type)
|
|
@@ -63,7 +63,7 @@ module Thrift
|
|
|
63
63
|
class StoredMessageProtocol < BaseProtocol
|
|
64
64
|
|
|
65
65
|
include ProtocolDecorator
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
def initialize(protocol, message_begin)
|
|
68
68
|
super(protocol)
|
|
69
69
|
@message_begin = message_begin
|
data/lib/thrift/processor.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
#
|
|
2
2
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
3
|
# or more contributor license agreements. See the NOTICE file
|
|
4
4
|
# distributed with this work for additional information
|
|
@@ -6,22 +6,22 @@
|
|
|
6
6
|
# to you under the Apache License, Version 2.0 (the
|
|
7
7
|
# "License"); you may not use this file except in compliance
|
|
8
8
|
# with the License. You may obtain a copy of the License at
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
11
|
+
#
|
|
12
12
|
# Unless required by applicable law or agreed to in writing,
|
|
13
13
|
# software distributed under the License is distributed on an
|
|
14
14
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
15
|
# KIND, either express or implied. See the License for the
|
|
16
16
|
# specific language governing permissions and limitations
|
|
17
17
|
# under the License.
|
|
18
|
-
#
|
|
18
|
+
#
|
|
19
19
|
|
|
20
20
|
require 'logger'
|
|
21
21
|
|
|
22
22
|
module Thrift
|
|
23
23
|
module Processor
|
|
24
|
-
def initialize(handler, logger=nil)
|
|
24
|
+
def initialize(handler, logger = nil)
|
|
25
25
|
@handler = handler
|
|
26
26
|
if logger.nil?
|
|
27
27
|
@logger = Logger.new(STDERR)
|
|
@@ -32,7 +32,7 @@ module Thrift
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def process(iprot, oprot)
|
|
35
|
-
name, type, seqid
|
|
35
|
+
name, type, seqid = iprot.read_message_begin
|
|
36
36
|
if respond_to?("process_#{name}")
|
|
37
37
|
begin
|
|
38
38
|
send("process_#{name}", seqid, iprot, oprot)
|