thrift 0.22.0 → 0.24.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 +235 -17
- data/benchmark/benchmark.rb +23 -8
- data/benchmark/client.rb +50 -6
- data/benchmark/server.rb +46 -7
- data/benchmark/thin_server.rb +2 -0
- data/ext/binary_protocol_accelerated.c +154 -42
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +138 -45
- data/ext/constants.h +12 -0
- data/ext/extconf.rb +17 -8
- data/ext/memory_buffer.c +44 -7
- data/ext/protocol.c +29 -0
- data/ext/protocol.h +35 -0
- data/ext/struct.c +48 -17
- data/ext/thrift_native.c +28 -3
- data/lib/thrift/bytes.rb +70 -100
- data/lib/thrift/client.rb +54 -13
- data/lib/thrift/exceptions.rb +6 -5
- data/lib/thrift/multiplexed_processor.rb +20 -10
- data/lib/thrift/processor.rb +7 -6
- data/lib/thrift/protocol/base_protocol.rb +52 -21
- data/lib/thrift/protocol/binary_protocol.rb +65 -20
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -5
- data/lib/thrift/protocol/compact_protocol.rb +76 -41
- data/lib/thrift/protocol/header_protocol.rb +321 -0
- data/lib/thrift/protocol/json_protocol.rb +44 -27
- data/lib/thrift/protocol/multiplexed_protocol.rb +6 -5
- data/lib/thrift/protocol/protocol_decorator.rb +13 -4
- data/lib/thrift/serializer/deserializer.rb +6 -5
- data/lib/thrift/serializer/serializer.rb +5 -5
- data/lib/thrift/server/base_server.rb +5 -4
- data/lib/thrift/server/mongrel_http_server.rb +7 -6
- data/lib/thrift/server/nonblocking_server.rb +35 -9
- data/lib/thrift/server/simple_server.rb +13 -5
- data/lib/thrift/server/thin_http_server.rb +4 -3
- data/lib/thrift/server/thread_pool_server.rb +7 -6
- data/lib/thrift/server/threaded_server.rb +13 -5
- data/lib/thrift/struct.rb +12 -11
- data/lib/thrift/struct_union.rb +14 -9
- data/lib/thrift/thrift_native.rb +3 -2
- data/lib/thrift/transport/base_server_transport.rb +8 -5
- data/lib/thrift/transport/base_transport.rb +18 -14
- data/lib/thrift/transport/buffered_transport.rb +7 -6
- data/lib/thrift/transport/framed_transport.rb +8 -7
- data/lib/thrift/transport/header_transport.rb +562 -0
- data/lib/thrift/transport/http_client_transport.rb +2 -1
- data/lib/thrift/transport/io_stream_transport.rb +4 -3
- data/lib/thrift/transport/memory_buffer_transport.rb +13 -6
- data/lib/thrift/transport/server_socket.rb +14 -8
- data/lib/thrift/transport/socket.rb +126 -60
- data/lib/thrift/transport/ssl_server_socket.rb +4 -3
- data/lib/thrift/transport/ssl_socket.rb +45 -13
- data/lib/thrift/transport/unix_server_socket.rb +9 -5
- data/lib/thrift/transport/unix_socket.rb +7 -6
- data/lib/thrift/types.rb +10 -6
- data/lib/thrift/union.rb +15 -8
- data/lib/thrift/uuid.rb +50 -0
- data/lib/thrift.rb +4 -1
- data/spec/ThriftSpec.thrift +21 -1
- data/spec/base_protocol_spec.rb +21 -2
- data/spec/base_transport_spec.rb +48 -8
- data/spec/binary_protocol_accelerated_spec.rb +1 -0
- data/spec/binary_protocol_spec.rb +1 -2
- data/spec/binary_protocol_spec_shared.rb +206 -155
- data/spec/bytes_spec.rb +71 -114
- data/spec/client_spec.rb +86 -19
- data/spec/compact_protocol_spec.rb +153 -16
- data/spec/constants_demo_spec.rb +102 -0
- data/spec/exception_spec.rb +1 -1
- data/spec/flat_spec.rb +1 -0
- data/spec/header_protocol_spec.rb +476 -0
- data/spec/header_transport_spec.rb +431 -0
- data/spec/http_client_spec.rb +5 -6
- data/spec/json_protocol_spec.rb +69 -47
- data/spec/multiplexed_processor_spec.rb +75 -0
- data/spec/namespaced_spec.rb +1 -1
- data/spec/nonblocking_server_spec.rb +174 -8
- data/spec/processor_spec.rb +1 -1
- data/spec/recursion_depth_spec.rb +223 -0
- data/spec/serializer_spec.rb +1 -1
- data/spec/server_socket_spec.rb +38 -1
- data/spec/server_spec.rb +60 -9
- data/spec/socket_spec.rb +119 -13
- data/spec/socket_spec_shared.rb +73 -9
- data/spec/spec_helper.rb +2 -1
- data/spec/ssl_server_socket_spec.rb +52 -1
- data/spec/ssl_socket_spec.rb +181 -11
- data/spec/struct_nested_containers_spec.rb +2 -2
- data/spec/struct_spec.rb +114 -9
- data/spec/support/header_protocol_helper.rb +55 -0
- data/spec/thin_http_server_spec.rb +4 -18
- data/spec/types_spec.rb +26 -26
- data/spec/union_spec.rb +70 -11
- data/spec/unix_socket_spec.rb +17 -2
- data/spec/uuid_validation_spec.rb +239 -0
- data/test/fuzz/Makefile +779 -0
- data/test/fuzz/Makefile.am +173 -0
- data/test/fuzz/Makefile.in +775 -0
- data/test/fuzz/README.md +149 -0
- data/test/fuzz/fuzz_common.rb +96 -0
- data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +4 -4
- data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +7 -13
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +23 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +23 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +23 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +23 -0
- data/test/fuzz/fuzz_tracer.rb +29 -0
- metadata +105 -70
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,22 @@ 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 void validate_container_size(int size) {
|
|
39
|
+
if (RB_UNLIKELY(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
|
+
|
|
49
|
+
static VALUE new_container_array(int size) {
|
|
50
|
+
validate_container_size(size);
|
|
51
|
+
return rb_ary_new2(size > 1024 ? 1024 : size);
|
|
52
|
+
}
|
|
53
|
+
|
|
37
54
|
//-------------------------------------------
|
|
38
55
|
// Writing section
|
|
39
56
|
//-------------------------------------------
|
|
@@ -75,6 +92,11 @@ VALUE default_write_string(VALUE protocol, VALUE value) {
|
|
|
75
92
|
return Qnil;
|
|
76
93
|
}
|
|
77
94
|
|
|
95
|
+
VALUE default_write_uuid(VALUE protocol, VALUE value) {
|
|
96
|
+
rb_funcall(protocol, write_uuid_method_id, 1, value);
|
|
97
|
+
return Qnil;
|
|
98
|
+
}
|
|
99
|
+
|
|
78
100
|
VALUE default_write_binary(VALUE protocol, VALUE value) {
|
|
79
101
|
rb_funcall(protocol, write_binary_method_id, 1, value);
|
|
80
102
|
return Qnil;
|
|
@@ -195,6 +217,10 @@ VALUE default_read_string(VALUE protocol) {
|
|
|
195
217
|
return rb_funcall(protocol, read_string_method_id, 0);
|
|
196
218
|
}
|
|
197
219
|
|
|
220
|
+
VALUE default_read_uuid(VALUE protocol) {
|
|
221
|
+
return rb_funcall(protocol, read_uuid_method_id, 0);
|
|
222
|
+
}
|
|
223
|
+
|
|
198
224
|
VALUE default_read_binary(VALUE protocol) {
|
|
199
225
|
return rb_funcall(protocol, read_binary_method_id, 0);
|
|
200
226
|
}
|
|
@@ -229,8 +255,6 @@ static void write_container(int ttype, VALUE field_info, VALUE value, VALUE prot
|
|
|
229
255
|
|
|
230
256
|
if (ttype == TTYPE_MAP) {
|
|
231
257
|
VALUE keys;
|
|
232
|
-
VALUE key;
|
|
233
|
-
VALUE val;
|
|
234
258
|
|
|
235
259
|
Check_Type(value, T_HASH);
|
|
236
260
|
|
|
@@ -249,8 +273,8 @@ static void write_container(int ttype, VALUE field_info, VALUE value, VALUE prot
|
|
|
249
273
|
default_write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));
|
|
250
274
|
|
|
251
275
|
for (i = 0; i < sz; i++) {
|
|
252
|
-
key = rb_ary_entry(keys, i);
|
|
253
|
-
val = rb_hash_aref(value, key);
|
|
276
|
+
VALUE key = rb_ary_entry(keys, i);
|
|
277
|
+
VALUE val = rb_hash_aref(value, key);
|
|
254
278
|
|
|
255
279
|
if (IS_CONTAINER(keytype)) {
|
|
256
280
|
write_container(keytype, key_info, key, protocol);
|
|
@@ -342,6 +366,8 @@ static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_i
|
|
|
342
366
|
} else {
|
|
343
367
|
default_write_binary(protocol, value);
|
|
344
368
|
}
|
|
369
|
+
} else if (ttype == TTYPE_UUID) {
|
|
370
|
+
default_write_uuid(protocol, value);
|
|
345
371
|
} else if (IS_CONTAINER(ttype)) {
|
|
346
372
|
write_container(ttype, field_info, value, protocol);
|
|
347
373
|
} else if (ttype == TTYPE_STRUCT) {
|
|
@@ -452,6 +478,8 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
452
478
|
}
|
|
453
479
|
} else if (ttype == TTYPE_DOUBLE) {
|
|
454
480
|
result = default_read_double(protocol);
|
|
481
|
+
} else if (ttype == TTYPE_UUID) {
|
|
482
|
+
result = default_read_uuid(protocol);
|
|
455
483
|
} else if (ttype == TTYPE_STRUCT) {
|
|
456
484
|
VALUE klass = rb_hash_aref(field_info, class_sym);
|
|
457
485
|
result = rb_class_new_instance(0, NULL, klass);
|
|
@@ -462,13 +490,15 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
462
490
|
rb_thrift_struct_read(result, protocol);
|
|
463
491
|
}
|
|
464
492
|
} else if (ttype == TTYPE_MAP) {
|
|
465
|
-
int i;
|
|
466
|
-
|
|
467
493
|
VALUE map_header = default_read_map_begin(protocol);
|
|
468
494
|
int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
|
|
469
495
|
int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
|
|
470
496
|
int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
|
|
471
497
|
|
|
498
|
+
if (num_entries < 0) {
|
|
499
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_NEGATIVE_SIZE), rb_str_new2("Negative container size")));
|
|
500
|
+
}
|
|
501
|
+
|
|
472
502
|
// Check the declared key and value types against the expected ones and skip the map contents
|
|
473
503
|
// if the types don't match.
|
|
474
504
|
VALUE key_info = rb_hash_aref(field_info, key_sym);
|
|
@@ -480,7 +510,7 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
480
510
|
if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) {
|
|
481
511
|
result = rb_hash_new();
|
|
482
512
|
|
|
483
|
-
for (i = 0; i < num_entries; ++i) {
|
|
513
|
+
for (int i = 0; i < num_entries; ++i) {
|
|
484
514
|
VALUE key, val;
|
|
485
515
|
|
|
486
516
|
key = read_anything(protocol, key_ttype, key_info);
|
|
@@ -497,8 +527,6 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
497
527
|
|
|
498
528
|
default_read_map_end(protocol);
|
|
499
529
|
} else if (ttype == TTYPE_LIST) {
|
|
500
|
-
int i;
|
|
501
|
-
|
|
502
530
|
VALUE list_header = default_read_list_begin(protocol);
|
|
503
531
|
int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
|
|
504
532
|
int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
|
|
@@ -509,22 +537,23 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
509
537
|
if (!NIL_P(element_info)) {
|
|
510
538
|
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
|
511
539
|
if (specified_element_type == element_ttype) {
|
|
512
|
-
result =
|
|
540
|
+
result = new_container_array(num_elements);
|
|
513
541
|
|
|
514
|
-
for (i = 0; i < num_elements; ++i) {
|
|
542
|
+
for (int i = 0; i < num_elements; ++i) {
|
|
515
543
|
rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
516
544
|
}
|
|
517
545
|
} else {
|
|
546
|
+
validate_container_size(num_elements);
|
|
518
547
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
519
548
|
}
|
|
520
549
|
} else {
|
|
550
|
+
validate_container_size(num_elements);
|
|
521
551
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
522
552
|
}
|
|
523
553
|
|
|
524
554
|
default_read_list_end(protocol);
|
|
525
555
|
} else if (ttype == TTYPE_SET) {
|
|
526
556
|
VALUE items;
|
|
527
|
-
int i;
|
|
528
557
|
|
|
529
558
|
VALUE set_header = default_read_set_begin(protocol);
|
|
530
559
|
int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
|
|
@@ -536,17 +565,19 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
|
536
565
|
if (!NIL_P(element_info)) {
|
|
537
566
|
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
|
538
567
|
if (specified_element_type == element_ttype) {
|
|
539
|
-
items =
|
|
568
|
+
items = new_container_array(num_elements);
|
|
540
569
|
|
|
541
|
-
for (i = 0; i < num_elements; ++i) {
|
|
570
|
+
for (int i = 0; i < num_elements; ++i) {
|
|
542
571
|
rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
|
543
572
|
}
|
|
544
573
|
|
|
545
574
|
result = rb_class_new_instance(1, &items, rb_cSet);
|
|
546
575
|
} else {
|
|
576
|
+
validate_container_size(num_elements);
|
|
547
577
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
548
578
|
}
|
|
549
579
|
} else {
|
|
580
|
+
validate_container_size(num_elements);
|
|
550
581
|
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
|
551
582
|
}
|
|
552
583
|
|
|
@@ -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,17 @@ 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
|
+
// cppcheck-suppress unusedFunction
|
|
125
|
+
RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
|
|
113
126
|
// cached classes
|
|
114
127
|
thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift"));
|
|
115
128
|
rb_global_variable(&thrift_module);
|
|
@@ -138,6 +151,7 @@ void Init_thrift_native() {
|
|
|
138
151
|
TTYPE_SET = FIX2INT(rb_const_get(thrift_types_module, rb_intern("SET")));
|
|
139
152
|
TTYPE_LIST = FIX2INT(rb_const_get(thrift_types_module, rb_intern("LIST")));
|
|
140
153
|
TTYPE_STRUCT = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRUCT")));
|
|
154
|
+
TTYPE_UUID = FIX2INT(rb_const_get(thrift_types_module, rb_intern("UUID")));
|
|
141
155
|
|
|
142
156
|
// method ids
|
|
143
157
|
validate_method_id = rb_intern("validate");
|
|
@@ -152,6 +166,7 @@ void Init_thrift_native() {
|
|
|
152
166
|
write_i64_method_id = rb_intern("write_i64");
|
|
153
167
|
write_double_method_id = rb_intern("write_double");
|
|
154
168
|
write_string_method_id = rb_intern("write_string");
|
|
169
|
+
write_uuid_method_id = rb_intern("write_uuid");
|
|
155
170
|
write_binary_method_id = rb_intern("write_binary");
|
|
156
171
|
write_map_begin_method_id = rb_intern("write_map_begin");
|
|
157
172
|
write_map_end_method_id = rb_intern("write_map_end");
|
|
@@ -165,10 +180,11 @@ void Init_thrift_native() {
|
|
|
165
180
|
read_i32_method_id = rb_intern("read_i32");
|
|
166
181
|
read_i64_method_id = rb_intern("read_i64");
|
|
167
182
|
read_string_method_id = rb_intern("read_string");
|
|
183
|
+
read_uuid_method_id = rb_intern("read_uuid");
|
|
168
184
|
read_binary_method_id = rb_intern("read_binary");
|
|
169
185
|
read_double_method_id = rb_intern("read_double");
|
|
170
186
|
read_map_begin_method_id = rb_intern("read_map_begin");
|
|
171
|
-
read_map_end_method_id = rb_intern("read_map_end");
|
|
187
|
+
read_map_end_method_id = rb_intern("read_map_end");
|
|
172
188
|
read_list_begin_method_id = rb_intern("read_list_begin");
|
|
173
189
|
read_list_end_method_id = rb_intern("read_list_end");
|
|
174
190
|
read_set_begin_method_id = rb_intern("read_set_begin");
|
|
@@ -192,7 +208,7 @@ void Init_thrift_native() {
|
|
|
192
208
|
fields_const_id = rb_intern("FIELDS");
|
|
193
209
|
transport_ivar_id = rb_intern("@trans");
|
|
194
210
|
strict_read_ivar_id = rb_intern("@strict_read");
|
|
195
|
-
strict_write_ivar_id = rb_intern("@strict_write");
|
|
211
|
+
strict_write_ivar_id = rb_intern("@strict_write");
|
|
196
212
|
|
|
197
213
|
// cached symbols
|
|
198
214
|
type_sym = ID2SYM(rb_intern("type"));
|
|
@@ -203,6 +219,15 @@ void Init_thrift_native() {
|
|
|
203
219
|
class_sym = ID2SYM(rb_intern("class"));
|
|
204
220
|
binary_sym = ID2SYM(rb_intern("binary"));
|
|
205
221
|
|
|
222
|
+
// protocol errors
|
|
223
|
+
PROTOERR_UNKNOWN = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("UNKNOWN")));
|
|
224
|
+
PROTOERR_INVALID_DATA = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("INVALID_DATA")));
|
|
225
|
+
PROTOERR_NEGATIVE_SIZE = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("NEGATIVE_SIZE")));
|
|
226
|
+
PROTOERR_SIZE_LIMIT = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("SIZE_LIMIT")));
|
|
227
|
+
PROTOERR_BAD_VERSION = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("BAD_VERSION")));
|
|
228
|
+
PROTOERR_NOT_IMPLEMENTED = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("NOT_IMPLEMENTED")));
|
|
229
|
+
PROTOERR_DEPTH_LIMIT = FIX2INT(rb_const_get(protocol_exception_class, rb_intern("DEPTH_LIMIT")));
|
|
230
|
+
|
|
206
231
|
rb_global_variable(&type_sym);
|
|
207
232
|
rb_global_variable(&name_sym);
|
|
208
233
|
rb_global_variable(&key_sym);
|
data/lib/thrift/bytes.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
5
6
|
# distributed with this work for additional information
|
|
@@ -7,9 +8,9 @@
|
|
|
7
8
|
# to you under the Apache License, Version 2.0 (the
|
|
8
9
|
# "License"); you may not use this file except in compliance
|
|
9
10
|
# with the License. You may obtain a copy of the License at
|
|
10
|
-
#
|
|
11
|
+
#
|
|
11
12
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
#
|
|
13
|
+
#
|
|
13
14
|
# Unless required by applicable law or agreed to in writing,
|
|
14
15
|
# software distributed under the License is distributed on an
|
|
15
16
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
@@ -21,111 +22,80 @@
|
|
|
21
22
|
module Thrift
|
|
22
23
|
# A collection of utilities for working with bytes and byte buffers.
|
|
23
24
|
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)
|
|
25
|
+
# Creates and empty byte buffer (String with BINARY encoding)
|
|
26
|
+
#
|
|
27
|
+
# size - The Integer size of the buffer (default: nil) to create
|
|
28
|
+
#
|
|
29
|
+
# Returns a String with BINARY encoding, filled with null characters
|
|
30
|
+
# if size is greater than zero
|
|
31
|
+
def self.empty_byte_buffer(size = nil)
|
|
32
|
+
if (size && size > 0)
|
|
33
|
+
"\0".b * size
|
|
34
|
+
else
|
|
35
|
+
''.b
|
|
87
36
|
end
|
|
37
|
+
end
|
|
88
38
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
else
|
|
99
|
-
def self.empty_byte_buffer(size = nil)
|
|
100
|
-
if (size && size > 0)
|
|
101
|
-
"\0" * size
|
|
102
|
-
else
|
|
103
|
-
''
|
|
104
|
-
end
|
|
105
|
-
end
|
|
39
|
+
# Forces the encoding of the buffer to BINARY. If the buffer
|
|
40
|
+
# passed is frozen and not already BINARY, 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
|
+
return buffer if buffer.encoding == Encoding::BINARY
|
|
106
48
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
49
|
+
buffer = buffer.dup if buffer.frozen?
|
|
50
|
+
buffer.force_encoding(Encoding::BINARY)
|
|
51
|
+
end
|
|
110
52
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
53
|
+
# Gets the byte value of a given position in a String.
|
|
54
|
+
#
|
|
55
|
+
# string - The String to retrive the byte value from.
|
|
56
|
+
# index - The Integer location of the byte value to retrieve.
|
|
57
|
+
#
|
|
58
|
+
# Returns an Integer value between 0 and 255.
|
|
59
|
+
def self.get_string_byte(string, index)
|
|
60
|
+
string.getbyte(index)
|
|
61
|
+
end
|
|
114
62
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
63
|
+
# Sets the byte value given to a given index in a String.
|
|
64
|
+
#
|
|
65
|
+
# string - The String to set the byte value in.
|
|
66
|
+
# index - The Integer location to set the byte value at.
|
|
67
|
+
# byte - The Integer value (0 to 255) to set in the string.
|
|
68
|
+
#
|
|
69
|
+
# Returns an Integer value of the byte value to set.
|
|
70
|
+
def self.set_string_byte(string, index, byte)
|
|
71
|
+
string.setbyte(index, byte)
|
|
72
|
+
end
|
|
118
73
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
74
|
+
# Converts the given String to a UTF-8 byte buffer.
|
|
75
|
+
#
|
|
76
|
+
# string - The String to convert.
|
|
77
|
+
#
|
|
78
|
+
# Returns a new String with BINARY encoding, containing the UTF-8
|
|
79
|
+
# bytes of the original string.
|
|
80
|
+
def self.convert_to_utf8_byte_buffer(string)
|
|
81
|
+
if string.encoding != Encoding::UTF_8
|
|
82
|
+
# transcode to UTF-8
|
|
83
|
+
string = string.encode(Encoding::UTF_8)
|
|
84
|
+
else
|
|
85
|
+
# encoding is already UTF-8, but a duplicate is needed
|
|
86
|
+
string = string.dup
|
|
123
87
|
end
|
|
88
|
+
string.force_encoding(Encoding::BINARY)
|
|
89
|
+
end
|
|
124
90
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
91
|
+
# Converts the given UTF-8 byte buffer into a String
|
|
92
|
+
#
|
|
93
|
+
# utf8_buffer - A String, with BINARY encoding, containing UTF-8 bytes
|
|
94
|
+
#
|
|
95
|
+
# Returns a new String with UTF-8 encoding,
|
|
96
|
+
def self.convert_to_string(utf8_buffer)
|
|
97
|
+
# duplicate the buffer, force encoding to UTF-8
|
|
98
|
+
utf8_buffer.dup.force_encoding(Encoding::UTF_8)
|
|
129
99
|
end
|
|
130
100
|
end
|
|
131
101
|
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
|
|
@@ -19,19 +20,25 @@
|
|
|
19
20
|
|
|
20
21
|
module Thrift
|
|
21
22
|
module Client
|
|
22
|
-
|
|
23
|
+
MIN_SEQUENCE_ID = -(2**31)
|
|
24
|
+
MAX_SEQUENCE_ID = (2**31) - 1
|
|
25
|
+
|
|
26
|
+
def initialize(iprot, oprot = nil)
|
|
23
27
|
@iprot = iprot
|
|
24
28
|
@oprot = oprot || iprot
|
|
25
29
|
@seqid = 0
|
|
30
|
+
@pending_seqids = []
|
|
26
31
|
end
|
|
27
32
|
|
|
28
33
|
def send_message(name, args_class, args = {})
|
|
29
|
-
|
|
34
|
+
seqid = next_seqid!
|
|
35
|
+
@oprot.write_message_begin(name, MessageTypes::CALL, seqid)
|
|
30
36
|
send_message_args(args_class, args)
|
|
37
|
+
@pending_seqids << seqid
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
def send_oneway_message(name, args_class, args = {})
|
|
34
|
-
@oprot.write_message_begin(name, MessageTypes::ONEWAY,
|
|
41
|
+
@oprot.write_message_begin(name, MessageTypes::ONEWAY, next_seqid!)
|
|
35
42
|
send_message_args(args_class, args)
|
|
36
43
|
end
|
|
37
44
|
|
|
@@ -55,9 +62,33 @@ module Thrift
|
|
|
55
62
|
[fname, mtype, rseqid]
|
|
56
63
|
end
|
|
57
64
|
|
|
58
|
-
def
|
|
59
|
-
|
|
60
|
-
|
|
65
|
+
def validate_message_begin(fname, mtype, rseqid, expected_name)
|
|
66
|
+
expected_seqid = dequeue_pending_seqid
|
|
67
|
+
|
|
68
|
+
if mtype == MessageTypes::EXCEPTION
|
|
69
|
+
raise_application_exception
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if mtype != MessageTypes::REPLY
|
|
73
|
+
raise ApplicationException.new(
|
|
74
|
+
ApplicationException::INVALID_MESSAGE_TYPE,
|
|
75
|
+
"#{expected_name} failed: invalid message type"
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
if fname != expected_name
|
|
80
|
+
raise ApplicationException.new(
|
|
81
|
+
ApplicationException::WRONG_METHOD_NAME,
|
|
82
|
+
"#{expected_name} failed: wrong method name"
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
return if !expected_seqid.nil? && rseqid == expected_seqid
|
|
87
|
+
|
|
88
|
+
raise ApplicationException.new(
|
|
89
|
+
ApplicationException::BAD_SEQUENCE_ID,
|
|
90
|
+
"#{expected_name} failed: out of sequence response"
|
|
91
|
+
)
|
|
61
92
|
end
|
|
62
93
|
|
|
63
94
|
def receive_message(result_klass)
|
|
@@ -67,13 +98,23 @@ module Thrift
|
|
|
67
98
|
result
|
|
68
99
|
end
|
|
69
100
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def next_seqid!
|
|
104
|
+
seqid = @seqid
|
|
105
|
+
@seqid = (seqid == MAX_SEQUENCE_ID) ? MIN_SEQUENCE_ID : seqid + 1
|
|
106
|
+
seqid
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def dequeue_pending_seqid
|
|
110
|
+
@pending_seqids.shift
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def raise_application_exception
|
|
114
|
+
x = ApplicationException.new
|
|
115
|
+
x.read(@iprot)
|
|
116
|
+
@iprot.read_message_end
|
|
117
|
+
raise x
|
|
77
118
|
end
|
|
78
119
|
end
|
|
79
120
|
end
|
data/lib/thrift/exceptions.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
4
5
|
# distributed with this work for additional information
|
|
@@ -6,16 +7,16 @@
|
|
|
6
7
|
# to you under the Apache License, Version 2.0 (the
|
|
7
8
|
# "License"); you may not use this file except in compliance
|
|
8
9
|
# with the License. You may obtain a copy of the License at
|
|
9
|
-
#
|
|
10
|
+
#
|
|
10
11
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
#
|
|
12
|
+
#
|
|
12
13
|
# Unless required by applicable law or agreed to in writing,
|
|
13
14
|
# software distributed under the License is distributed on an
|
|
14
15
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
16
|
# KIND, either express or implied. See the License for the
|
|
16
17
|
# specific language governing permissions and limitations
|
|
17
18
|
# under the License.
|
|
18
|
-
#
|
|
19
|
+
#
|
|
19
20
|
|
|
20
21
|
module Thrift
|
|
21
22
|
class Exception < StandardError
|
|
@@ -43,7 +44,7 @@ module Thrift
|
|
|
43
44
|
|
|
44
45
|
attr_reader :type
|
|
45
46
|
|
|
46
|
-
def initialize(type=UNKNOWN, message=nil)
|
|
47
|
+
def initialize(type = UNKNOWN, message = nil)
|
|
47
48
|
super(message)
|
|
48
49
|
@type = type
|
|
49
50
|
end
|