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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0eacf1574da356dba55962561224cd683bf1c073e531b8402f469e91cb964dd8
|
|
4
|
+
data.tar.gz: b7f8aed51a240fab797e8137d56bd65c25d04291b292be40b3475831b945d4f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35f22ce7f4d25a25c18611548eaf575a33a62bdd3a673876ac36fa783ccb44bd7b0066ebf2b1158ad6687aaf49182a9af2a9f6c1955addcf71e8c7738f615a66
|
|
7
|
+
data.tar.gz: 0edd8cdaccb60eb0082da2aed7169f46b167ef821d68ba126c22945738165d20bca3a505fb09969c8abb5dccd212ea23d296ffcc02c2b6e46a29d361e925efcf
|
data/README.md
CHANGED
|
@@ -27,7 +27,7 @@ clients and services.
|
|
|
27
27
|
|
|
28
28
|
## Compatibility
|
|
29
29
|
|
|
30
|
-
- Ruby MRI >=
|
|
30
|
+
- Ruby MRI >= 3.0 (tested against current supported releases).
|
|
31
31
|
- JRuby works with the pure-Ruby implementation; the native extension is
|
|
32
32
|
skipped automatically.
|
|
33
33
|
- For the repo-wide transport, protocol, and server support matrix, see
|
|
@@ -36,7 +36,7 @@ clients and services.
|
|
|
36
36
|
|
|
37
37
|
## Installation
|
|
38
38
|
|
|
39
|
-
- Requirements: Ruby >=
|
|
39
|
+
- Requirements: Ruby >= 3.0.
|
|
40
40
|
- From RubyGems: `gem install thrift`
|
|
41
41
|
- From source: `bundle install`, `gem build thrift.gemspec`, then install the
|
|
42
42
|
resulting `thrift-*.gem`. The native accelerator is built when the gem is
|
|
@@ -47,49 +47,80 @@ clients and services.
|
|
|
47
47
|
The Ruby library does not include the Thrift compiler. Use a compiler built
|
|
48
48
|
from the root of this repository to generate Ruby bindings:
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
```bash
|
|
51
|
+
thrift --gen rb path/to/service.thrift
|
|
52
|
+
# with namespaced modules
|
|
53
|
+
thrift --gen rb:namespaced --recurse path/to/service.thrift
|
|
54
|
+
```
|
|
53
55
|
|
|
54
56
|
Generated files are typically written to `gen-rb/` and can be required
|
|
55
57
|
directly from your application.
|
|
56
58
|
|
|
57
59
|
## Basic Client Usage
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
```ruby
|
|
62
|
+
$:.push File.expand_path('gen-rb', __dir__)
|
|
63
|
+
require 'thrift'
|
|
64
|
+
require 'calculator'
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
socket = Thrift::Socket.new('localhost', 9090)
|
|
67
|
+
transport = Thrift::BufferedTransport.new(socket)
|
|
68
|
+
protocol = Thrift::BinaryProtocol.new(transport)
|
|
69
|
+
client = Calculator::Client.new(protocol)
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
transport.open
|
|
72
|
+
puts client.add(1, 1)
|
|
73
|
+
transport.close
|
|
74
|
+
```
|
|
71
75
|
|
|
72
76
|
## Basic Server Usage
|
|
73
77
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
78
|
+
```ruby
|
|
79
|
+
$:.push File.expand_path('gen-rb', __dir__)
|
|
80
|
+
require 'thrift'
|
|
81
|
+
require 'calculator'
|
|
82
|
+
|
|
83
|
+
class CalculatorHandler
|
|
84
|
+
def add(a, b)
|
|
85
|
+
a + b
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
handler = CalculatorHandler.new
|
|
90
|
+
processor = Calculator::Processor.new(handler)
|
|
91
|
+
server_transport = Thrift::ServerSocket.new(9090)
|
|
92
|
+
transport_factory = Thrift::BufferedTransportFactory.new
|
|
93
|
+
protocol_factory = Thrift::BinaryProtocolFactory.new
|
|
94
|
+
|
|
95
|
+
server = Thrift::ThreadedServer.new(processor, server_transport,
|
|
96
|
+
transport_factory, protocol_factory)
|
|
97
|
+
server.serve
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Rack HTTP Endpoint
|
|
101
|
+
|
|
102
|
+
Ruby HTTP transport can be mounted as a Rack application, so applications can
|
|
103
|
+
run Thrift on an existing Rack server such as Puma or Falcon.
|
|
104
|
+
The examples below use the generated `Calculator::Processor` and the
|
|
105
|
+
`CalculatorHandler` from [Basic Server Usage](#basic-server-usage).
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
# config.ru
|
|
109
|
+
require 'thrift'
|
|
110
|
+
require 'thrift/server/rack_application'
|
|
111
|
+
|
|
112
|
+
processor = Calculator::Processor.new(CalculatorHandler.new)
|
|
113
|
+
run Thrift::RackApplication.new(processor)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
For Rails or another Rack router, mount the endpoint at the route that should
|
|
117
|
+
receive Thrift HTTP requests:
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
# config/routes.rb
|
|
121
|
+
processor = Calculator::Processor.new(CalculatorHandler.new)
|
|
122
|
+
mount Thrift::RackApplication.new(processor) => "/thrift"
|
|
123
|
+
```
|
|
93
124
|
|
|
94
125
|
## Development and Tests
|
|
95
126
|
|
|
@@ -111,6 +142,109 @@ directly from your application.
|
|
|
111
142
|
|
|
112
143
|
## Breaking Changes
|
|
113
144
|
|
|
145
|
+
### 0.25.0
|
|
146
|
+
|
|
147
|
+
Ruby 2.7 support has been removed because the runtime reached end of life on
|
|
148
|
+
March 31, 2023. The Thrift gem now requires Ruby 3.0 or newer. Applications
|
|
149
|
+
still running Ruby 2.7 must upgrade Ruby before installing Thrift 0.25.0 or
|
|
150
|
+
remain on an earlier Thrift release.
|
|
151
|
+
|
|
152
|
+
Ruby HTTP servers now share one Rack endpoint. Run `Thrift::RackApplication`
|
|
153
|
+
as a Rack app, or mount it at one path in an app such as Rails. The
|
|
154
|
+
cross-language HTTP tests now cover Puma and Falcon.
|
|
155
|
+
|
|
156
|
+
`Thrift::MongrelHTTPServer` has been removed because Mongrel no longer works
|
|
157
|
+
with supported Ruby versions. To migrate, mount `Thrift::RackApplication` in
|
|
158
|
+
a supported Rack server. See [Rack HTTP Endpoint](#rack-http-endpoint).
|
|
159
|
+
|
|
160
|
+
`Thrift::ThinHTTPServer` is deprecated because Thin is no longer maintained.
|
|
161
|
+
Its EventMachine dependency also does not build on new Ruby development
|
|
162
|
+
versions. Creating a Thin server now prints a warning. Move to
|
|
163
|
+
`Thrift::RackApplication` with a supported Rack server such as Puma or Falcon.
|
|
164
|
+
|
|
165
|
+
`Thrift::SSLSocket` now verifies peers by default when no SSL context is
|
|
166
|
+
provided. It creates a context that uses the system certificate store. A
|
|
167
|
+
supplied SSL context is not reconfigured by Thrift, so the application is
|
|
168
|
+
responsible for its verification mode and trust sources. A newly constructed
|
|
169
|
+
`OpenSSL::SSL::SSLContext` defaults to `OpenSSL::SSL::VERIFY_NONE`; configuring
|
|
170
|
+
a trust source alone does not enable certificate chain verification. The server
|
|
171
|
+
certificate must still match the connection hostname.
|
|
172
|
+
|
|
173
|
+
`Thrift::NonblockingServer` now closes a connection whose frame declares more than
|
|
174
|
+
`max_frame_size` before it collects the frame. `max_frame_size` is a new keyword argument
|
|
175
|
+
and defaults to `Thrift::FramedTransport::DEFAULT_MAX_FRAME_SIZE` (16,384,000 bytes), the
|
|
176
|
+
limit `FramedTransport` already applies to the frame the worker reads back. A server that
|
|
177
|
+
accepted larger frames must pass a higher `max_frame_size:` to keep doing so.
|
|
178
|
+
|
|
179
|
+
`Thrift::Socket#open` now raises
|
|
180
|
+
`Thrift::TransportException::ALREADY_OPEN` when the TCP transport is already
|
|
181
|
+
open. Close the transport before opening it again.
|
|
182
|
+
|
|
183
|
+
Ruby struct, union, and exception serialization methods now accept an optional
|
|
184
|
+
remaining struct depth: `read(protocol, depth = 64)` and
|
|
185
|
+
`write(protocol, depth = 64)`.
|
|
186
|
+
Unknown and mismatched fields remain independently bounded by
|
|
187
|
+
`Thrift::BaseProtocol#skip`. The `write_field` and `write_type` helpers accept
|
|
188
|
+
an optional `remaining_depth`: custom writers must use
|
|
189
|
+
`write_field(field_info, fid, value, remaining_depth)` or
|
|
190
|
+
`write_type(field_info, value, remaining_depth)` for struct values. Custom
|
|
191
|
+
protocols and custom struct, union, or exception serialization overrides with
|
|
192
|
+
exact argument counts must accept and forward the optional depth argument (or
|
|
193
|
+
use `*args`) before upgrading.
|
|
194
|
+
|
|
195
|
+
`Thrift::BinaryProtocol`, `Thrift::BinaryProtocolAccelerated` and `Thrift::CompactProtocol`
|
|
196
|
+
now refuse a string or binary field longer than `max_string_size` before reading it,
|
|
197
|
+
with a `ProtocolException` of type `SIZE_LIMIT`. The maximum defaults to
|
|
198
|
+
`Thrift::BaseProtocol::DEFAULT_MAX_STRING_SIZE`, 16384000 bytes, the frame size limit
|
|
199
|
+
the framed transports apply, and is a keyword argument of the three protocols and
|
|
200
|
+
their factories. Pass `max_string_size: nil` to read strings of any length, as before.
|
|
201
|
+
|
|
202
|
+
### 0.24.0
|
|
203
|
+
|
|
204
|
+
Connect timeout handling changed for both `Thrift::Socket` and
|
|
205
|
+
`Thrift::SSLSocket`.
|
|
206
|
+
|
|
207
|
+
- `timeout == nil` and `timeout == 0` now use blocking connect/open semantics.
|
|
208
|
+
Older releases already treated `nil` that way, but treated `0` differently
|
|
209
|
+
across operations: `read` and `write` used the blocking path, plain TCP
|
|
210
|
+
`open` used a zero-length poll, and TLS `open` could spin in the handshake
|
|
211
|
+
retry loop.
|
|
212
|
+
- Positive timeouts now bound the whole connect/open operation instead of
|
|
213
|
+
effectively applying a fresh timeout window at each wait or address attempt.
|
|
214
|
+
For plain TCP this budget is shared across address fallback. For TLS it is
|
|
215
|
+
shared across the TCP connect and the SSL handshake.
|
|
216
|
+
- Connect/open timeout expiry now raises
|
|
217
|
+
`Thrift::TransportException::TIMED_OUT`. Older releases could report the same
|
|
218
|
+
condition as `NOT_OPEN`, and `Thrift::SSLSocket` could keep retrying the
|
|
219
|
+
handshake after the wait timed out.
|
|
220
|
+
|
|
221
|
+
If your application matched `NOT_OPEN` for connect timeout handling, update it
|
|
222
|
+
to handle `TIMED_OUT`. If you relied on `timeout = 0` meaning immediate failure
|
|
223
|
+
or on repeated retries extending the effective timeout during TCP fallback or
|
|
224
|
+
TLS handshake, update those call paths before upgrading.
|
|
225
|
+
|
|
226
|
+
Ruby server socket transports now apply a 5-second timeout to accepted client
|
|
227
|
+
sockets by default. This prevents stalled clients from blocking server threads
|
|
228
|
+
indefinitely during response writes. Applications that intentionally require
|
|
229
|
+
blocking accepted sockets can pass `client_timeout: nil` or `client_timeout: 0`
|
|
230
|
+
when constructing `Thrift::ServerSocket`, `Thrift::SSLServerSocket`, or
|
|
231
|
+
`Thrift::UNIXServerSocket`.
|
|
232
|
+
|
|
233
|
+
Generated Ruby structs and unions now suffix field ID constants as
|
|
234
|
+
`*_FIELD_ID` instead of exposing bare uppercased field names. For example,
|
|
235
|
+
`MyStruct::FOO` becomes `MyStruct::FOO_FIELD_ID`. This avoids collisions with
|
|
236
|
+
the generated `FIELDS` metadata hash for field names such as `fields`, but it
|
|
237
|
+
is a source-compatible break if your application referenced the old constants
|
|
238
|
+
directly. Regenerate Ruby code and update those constant references atomically.
|
|
239
|
+
|
|
240
|
+
Ruby binary protocol writers now enforce signed Thrift integer ranges before
|
|
241
|
+
serializing values. `byte`, `i16`, `i32`, and `i64` writes reject values outside
|
|
242
|
+
their declared signed ranges, and binary/string/container sizes must fit in a
|
|
243
|
+
non-negative signed `i32` length. Older releases could silently wrap or clip
|
|
244
|
+
some out-of-range values, such as writing `255` as a byte that read back as
|
|
245
|
+
`-1`. This applies to both `Thrift::BinaryProtocol` and
|
|
246
|
+
`Thrift::BinaryProtocolAccelerated`.
|
|
247
|
+
|
|
114
248
|
### 0.23.0
|
|
115
249
|
|
|
116
250
|
The documented source-build flow now effectively requires Ruby `2.7+`.
|
|
@@ -157,14 +291,30 @@ best-effort, not guaranteed.
|
|
|
157
291
|
`thrift --gen rb` and namespaced output from `thrift --gen rb:namespaced`
|
|
158
292
|
use different require paths, so switch them atomically with regenerated code.
|
|
159
293
|
|
|
160
|
-
|
|
161
|
-
|
|
294
|
+
```ruby
|
|
295
|
+
# --gen rb
|
|
296
|
+
require 'calculator'
|
|
162
297
|
|
|
163
|
-
|
|
164
|
-
|
|
298
|
+
# --gen rb:namespaced
|
|
299
|
+
require 'my_namespace/calculator'
|
|
300
|
+
```
|
|
165
301
|
|
|
166
302
|
## Migration Notes
|
|
167
303
|
|
|
304
|
+
- If you upgrade to `0.25.0`, note that `Thrift::SSLSocket` now verifies peers
|
|
305
|
+
by default when it creates the SSL context. Supplied contexts are used
|
|
306
|
+
unchanged and must configure their own verification mode and trust sources.
|
|
307
|
+
A blank supplied context defaults to `OpenSSL::SSL::VERIFY_NONE`. Hostname
|
|
308
|
+
checking is performed for both supplied and default contexts.
|
|
309
|
+
- If you upgrade to `0.25.0`, close a `Thrift::Socket` before calling `open`
|
|
310
|
+
again. A duplicate open now raises
|
|
311
|
+
`Thrift::TransportException::ALREADY_OPEN`.
|
|
312
|
+
- If you upgrade to `0.24.0`, treat `timeout` on `Thrift::Socket` and
|
|
313
|
+
`Thrift::SSLSocket` as one budget for the whole open path. For
|
|
314
|
+
`Thrift::SSLSocket`, that includes both the TCP connect and the TLS
|
|
315
|
+
handshake.
|
|
316
|
+
- If you upgrade to `0.24.0`, handle connect/open timeout expiry as
|
|
317
|
+
`Thrift::TransportException::TIMED_OUT` instead of `NOT_OPEN`.
|
|
168
318
|
- If you upgrade across the stricter reply-validation changes, regenerate all
|
|
169
319
|
Ruby stubs and deploy them with the matching Ruby runtime. Do not mix old
|
|
170
320
|
generated code, new generated code, and new runtime code on the same client
|
|
@@ -197,5 +347,18 @@ best-effort, not guaranteed.
|
|
|
197
347
|
- Client and server must agree on transport and protocol choices. If you
|
|
198
348
|
switch to SSL, HTTP, header transport, compact protocol, or namespaced
|
|
199
349
|
generated code, update both ends together.
|
|
200
|
-
- HTTPS client transport
|
|
201
|
-
|
|
350
|
+
- HTTPS client transport and `Thrift::SSLSocket` verify peers by default.
|
|
351
|
+
When no SSL context is provided, `Thrift::SSLSocket` creates one with peer
|
|
352
|
+
verification and the system certificate store. Thrift passes a supplied
|
|
353
|
+
context to OpenSSL without reconfiguring it. `Thrift::SSLSocket` always
|
|
354
|
+
checks the certificate against `server_hostname` (or the connection host by
|
|
355
|
+
default). `OpenSSL::SSL::SSLContext.new` defaults to
|
|
356
|
+
`OpenSSL::SSL::VERIFY_NONE`, and setting `ca_file`, `ca_path`, or `cert_store`
|
|
357
|
+
does not enable verification by itself. Set `verify_mode` explicitly when
|
|
358
|
+
supplying a context. For example, to disable certificate chain verification:
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
context = OpenSSL::SSL::SSLContext.new
|
|
362
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
363
|
+
socket = Thrift::SSLSocket.new(host, port, nil, context)
|
|
364
|
+
```
|
|
@@ -31,13 +31,59 @@ VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
|
|
|
31
31
|
return Qtrue;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
34
|
static int VERSION_1;
|
|
37
35
|
static int VERSION_MASK;
|
|
38
36
|
static int TYPE_MASK;
|
|
39
37
|
static ID rbuf_ivar_id;
|
|
40
38
|
|
|
39
|
+
static int64_t checked_integer_value(VALUE value) {
|
|
40
|
+
if (!RB_INTEGER_TYPE_P(value)) {
|
|
41
|
+
rb_raise(rb_eTypeError, "integer argument expected");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return NUM2LL(value);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static int64_t checked_integer_range(VALUE value, int64_t min, int64_t max) {
|
|
48
|
+
int64_t integer = checked_integer_value(value);
|
|
49
|
+
|
|
50
|
+
if (integer < min || integer > max) {
|
|
51
|
+
rb_raise(rb_eRangeError, "integer out of bounds");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return integer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static int8_t checked_byte_value(VALUE value) {
|
|
58
|
+
return (int8_t)checked_integer_range(value, INT8_MIN, INT8_MAX);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static int16_t checked_i16_value(VALUE value) {
|
|
62
|
+
return (int16_t)checked_integer_range(value, INT16_MIN, INT16_MAX);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static int32_t checked_i32_value(VALUE value) {
|
|
66
|
+
return (int32_t)checked_integer_range(value, INT32_MIN, INT32_MAX);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static int32_t checked_size_value(VALUE value) {
|
|
70
|
+
return (int32_t)checked_integer_range(value, 0, INT32_MAX);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static int64_t checked_i64_value(VALUE value) {
|
|
74
|
+
return checked_integer_range(value, INT64_MIN, INT64_MAX);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static int32_t checked_string_length(VALUE str) {
|
|
78
|
+
long length = RSTRING_LEN(str);
|
|
79
|
+
|
|
80
|
+
if (length > INT32_MAX) {
|
|
81
|
+
rb_raise(rb_eRangeError, "string too long");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (int32_t)length;
|
|
85
|
+
}
|
|
86
|
+
|
|
41
87
|
static void write_byte_direct(VALUE trans, int8_t b) {
|
|
42
88
|
WRITE(trans, (char*)&b, 1);
|
|
43
89
|
}
|
|
@@ -83,7 +129,7 @@ static void write_string_direct(VALUE trans, VALUE str) {
|
|
|
83
129
|
rb_raise(rb_eStandardError, "Value should be a string");
|
|
84
130
|
}
|
|
85
131
|
str = convert_to_utf8_byte_buffer(str);
|
|
86
|
-
write_i32_direct(trans, (
|
|
132
|
+
write_i32_direct(trans, checked_string_length(str));
|
|
87
133
|
rb_funcall(trans, write_method_id, 1, str);
|
|
88
134
|
}
|
|
89
135
|
|
|
@@ -124,13 +170,14 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
|
|
|
124
170
|
VALUE strict_write = GET_STRICT_WRITE(self);
|
|
125
171
|
|
|
126
172
|
if (strict_write == Qtrue) {
|
|
127
|
-
|
|
173
|
+
int8_t message_type = checked_byte_value(type);
|
|
174
|
+
write_i32_direct(trans, VERSION_1 | message_type);
|
|
128
175
|
write_string_direct(trans, name);
|
|
129
|
-
write_i32_direct(trans,
|
|
176
|
+
write_i32_direct(trans, checked_i32_value(seqid));
|
|
130
177
|
} else {
|
|
131
178
|
write_string_direct(trans, name);
|
|
132
|
-
write_byte_direct(trans,
|
|
133
|
-
write_i32_direct(trans,
|
|
179
|
+
write_byte_direct(trans, checked_byte_value(type));
|
|
180
|
+
write_i32_direct(trans, checked_i32_value(seqid));
|
|
134
181
|
}
|
|
135
182
|
|
|
136
183
|
return Qnil;
|
|
@@ -138,8 +185,8 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
|
|
|
138
185
|
|
|
139
186
|
VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
|
|
140
187
|
VALUE trans = GET_TRANSPORT(self);
|
|
141
|
-
write_byte_direct(trans,
|
|
142
|
-
write_i16_direct(trans,
|
|
188
|
+
write_byte_direct(trans, checked_byte_value(type));
|
|
189
|
+
write_i16_direct(trans, checked_i16_value(id));
|
|
143
190
|
|
|
144
191
|
return Qnil;
|
|
145
192
|
}
|
|
@@ -151,17 +198,17 @@ VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) {
|
|
|
151
198
|
|
|
152
199
|
VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) {
|
|
153
200
|
VALUE trans = GET_TRANSPORT(self);
|
|
154
|
-
write_byte_direct(trans,
|
|
155
|
-
write_byte_direct(trans,
|
|
156
|
-
write_i32_direct(trans,
|
|
201
|
+
write_byte_direct(trans, checked_byte_value(ktype));
|
|
202
|
+
write_byte_direct(trans, checked_byte_value(vtype));
|
|
203
|
+
write_i32_direct(trans, checked_size_value(size));
|
|
157
204
|
|
|
158
205
|
return Qnil;
|
|
159
206
|
}
|
|
160
207
|
|
|
161
208
|
VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) {
|
|
162
209
|
VALUE trans = GET_TRANSPORT(self);
|
|
163
|
-
write_byte_direct(trans,
|
|
164
|
-
write_i32_direct(trans,
|
|
210
|
+
write_byte_direct(trans, checked_byte_value(etype));
|
|
211
|
+
write_i32_direct(trans, checked_size_value(size));
|
|
165
212
|
|
|
166
213
|
return Qnil;
|
|
167
214
|
}
|
|
@@ -178,25 +225,25 @@ VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) {
|
|
|
178
225
|
|
|
179
226
|
VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) {
|
|
180
227
|
CHECK_NIL(byte);
|
|
181
|
-
write_byte_direct(GET_TRANSPORT(self),
|
|
228
|
+
write_byte_direct(GET_TRANSPORT(self), checked_byte_value(byte));
|
|
182
229
|
return Qnil;
|
|
183
230
|
}
|
|
184
231
|
|
|
185
232
|
VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) {
|
|
186
233
|
CHECK_NIL(i16);
|
|
187
|
-
write_i16_direct(GET_TRANSPORT(self),
|
|
234
|
+
write_i16_direct(GET_TRANSPORT(self), checked_i16_value(i16));
|
|
188
235
|
return Qnil;
|
|
189
236
|
}
|
|
190
237
|
|
|
191
238
|
VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) {
|
|
192
239
|
CHECK_NIL(i32);
|
|
193
|
-
write_i32_direct(GET_TRANSPORT(self),
|
|
240
|
+
write_i32_direct(GET_TRANSPORT(self), checked_i32_value(i32));
|
|
194
241
|
return Qnil;
|
|
195
242
|
}
|
|
196
243
|
|
|
197
244
|
VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) {
|
|
198
245
|
CHECK_NIL(i64);
|
|
199
|
-
write_i64_direct(GET_TRANSPORT(self),
|
|
246
|
+
write_i64_direct(GET_TRANSPORT(self), checked_i64_value(i64));
|
|
200
247
|
return Qnil;
|
|
201
248
|
}
|
|
202
249
|
|
|
@@ -224,7 +271,7 @@ VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) {
|
|
|
224
271
|
CHECK_NIL(buf);
|
|
225
272
|
VALUE trans = GET_TRANSPORT(self);
|
|
226
273
|
buf = force_binary_encoding(buf);
|
|
227
|
-
write_i32_direct(trans, (
|
|
274
|
+
write_i32_direct(trans, checked_string_length(buf));
|
|
228
275
|
rb_funcall(trans, write_method_id, 1, buf);
|
|
229
276
|
return Qnil;
|
|
230
277
|
}
|
|
@@ -284,33 +331,62 @@ static char read_byte_direct(VALUE self) {
|
|
|
284
331
|
return (char)(FIX2INT(byte));
|
|
285
332
|
}
|
|
286
333
|
|
|
334
|
+
static int16_t uint16_to_int16(uint16_t value) {
|
|
335
|
+
if (value <= INT16_MAX) {
|
|
336
|
+
return (int16_t)value;
|
|
337
|
+
}
|
|
338
|
+
return (int16_t)((int32_t)value - ((int32_t)UINT16_MAX + 1));
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
static int32_t uint32_to_int32(uint32_t value) {
|
|
342
|
+
if (value <= INT32_MAX) {
|
|
343
|
+
return (int32_t)value;
|
|
344
|
+
}
|
|
345
|
+
return (int32_t)((int64_t)value - (INT64_C(1) << 32));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
static int64_t uint64_to_int64(uint64_t value) {
|
|
349
|
+
if (value <= INT64_MAX) {
|
|
350
|
+
return (int64_t)value;
|
|
351
|
+
}
|
|
352
|
+
return -(int64_t)(~value) - INT64_C(1);
|
|
353
|
+
}
|
|
354
|
+
|
|
287
355
|
static int16_t read_i16_direct(VALUE self) {
|
|
288
356
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
289
357
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(2));
|
|
290
|
-
|
|
358
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
359
|
+
uint16_t value = ((uint16_t)bytes[0] << 8) | (uint16_t)bytes[1];
|
|
360
|
+
return uint16_to_int16(value);
|
|
291
361
|
}
|
|
292
362
|
|
|
293
363
|
static int32_t read_i32_direct(VALUE self) {
|
|
294
364
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
295
365
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(4));
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
((
|
|
299
|
-
((
|
|
366
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
367
|
+
uint32_t value = ((uint32_t)bytes[0] << 24) |
|
|
368
|
+
((uint32_t)bytes[1] << 16) |
|
|
369
|
+
((uint32_t)bytes[2] << 8) |
|
|
370
|
+
(uint32_t)bytes[3];
|
|
371
|
+
return uint32_to_int32(value);
|
|
300
372
|
}
|
|
301
373
|
|
|
302
|
-
static
|
|
374
|
+
static uint64_t read_u64_direct(VALUE self) {
|
|
303
375
|
VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id);
|
|
304
376
|
rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8));
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
((
|
|
308
|
-
((
|
|
309
|
-
|
|
310
|
-
((
|
|
311
|
-
((
|
|
312
|
-
((
|
|
313
|
-
|
|
377
|
+
const uint8_t* bytes = (const uint8_t*)RSTRING_PTR(rbuf);
|
|
378
|
+
return ((uint64_t)bytes[0] << 56) |
|
|
379
|
+
((uint64_t)bytes[1] << 48) |
|
|
380
|
+
((uint64_t)bytes[2] << 40) |
|
|
381
|
+
((uint64_t)bytes[3] << 32) |
|
|
382
|
+
((uint64_t)bytes[4] << 24) |
|
|
383
|
+
((uint64_t)bytes[5] << 16) |
|
|
384
|
+
((uint64_t)bytes[6] << 8) |
|
|
385
|
+
(uint64_t)bytes[7];
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
static int64_t read_i64_direct(VALUE self) {
|
|
389
|
+
return uint64_to_int64(read_u64_direct(self));
|
|
314
390
|
}
|
|
315
391
|
|
|
316
392
|
VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
|
|
@@ -346,6 +422,10 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
|
|
|
346
422
|
VALUE name, seqid;
|
|
347
423
|
int type;
|
|
348
424
|
|
|
425
|
+
if (RTEST(rb_ivar_get(self, reset_message_size_ivar_id))) {
|
|
426
|
+
rb_funcall(GET_TRANSPORT(self), reset_message_size_method_id, 0);
|
|
427
|
+
}
|
|
428
|
+
|
|
349
429
|
int version = read_i32_direct(self);
|
|
350
430
|
|
|
351
431
|
if (version < 0) {
|
|
@@ -359,6 +439,7 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
|
|
|
359
439
|
if (strict_read == Qtrue) {
|
|
360
440
|
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
|
|
361
441
|
}
|
|
442
|
+
CHECK_STRING_SIZE(self, version);
|
|
362
443
|
name = READ(self, version);
|
|
363
444
|
type = read_byte_direct(self);
|
|
364
445
|
seqid = rb_thrift_binary_proto_read_i32(self);
|
|
@@ -377,17 +458,24 @@ VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) {
|
|
|
377
458
|
}
|
|
378
459
|
}
|
|
379
460
|
|
|
461
|
+
#define CHECK_NEGATIVE_SIZE(size) \
|
|
462
|
+
if (RB_UNLIKELY((size) < 0)) { \
|
|
463
|
+
rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_NEGATIVE_SIZE), rb_str_new2("Negative size"))); \
|
|
464
|
+
}
|
|
465
|
+
|
|
380
466
|
VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) {
|
|
381
467
|
VALUE ktype = rb_thrift_binary_proto_read_byte(self);
|
|
382
468
|
VALUE vtype = rb_thrift_binary_proto_read_byte(self);
|
|
383
|
-
|
|
384
|
-
|
|
469
|
+
int size = read_i32_direct(self);
|
|
470
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
471
|
+
return rb_ary_new3(3, ktype, vtype, INT2NUM(size));
|
|
385
472
|
}
|
|
386
473
|
|
|
387
474
|
VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) {
|
|
388
475
|
VALUE etype = rb_thrift_binary_proto_read_byte(self);
|
|
389
|
-
|
|
390
|
-
|
|
476
|
+
int size = read_i32_direct(self);
|
|
477
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
478
|
+
return rb_ary_new3(2, etype, INT2NUM(size));
|
|
391
479
|
}
|
|
392
480
|
|
|
393
481
|
VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) {
|
|
@@ -418,9 +506,9 @@ VALUE rb_thrift_binary_proto_read_i64(VALUE self) {
|
|
|
418
506
|
VALUE rb_thrift_binary_proto_read_double(VALUE self) {
|
|
419
507
|
union {
|
|
420
508
|
double f;
|
|
421
|
-
|
|
509
|
+
uint64_t t;
|
|
422
510
|
} transfer;
|
|
423
|
-
transfer.t =
|
|
511
|
+
transfer.t = read_u64_direct(self);
|
|
424
512
|
return rb_float_new(transfer.f);
|
|
425
513
|
}
|
|
426
514
|
|
|
@@ -431,6 +519,8 @@ VALUE rb_thrift_binary_proto_read_string(VALUE self) {
|
|
|
431
519
|
|
|
432
520
|
VALUE rb_thrift_binary_proto_read_binary(VALUE self) {
|
|
433
521
|
int size = read_i32_direct(self);
|
|
522
|
+
CHECK_NEGATIVE_SIZE(size);
|
|
523
|
+
CHECK_STRING_SIZE(self, size);
|
|
434
524
|
return READ(self, size);
|
|
435
525
|
}
|
|
436
526
|
|
data/ext/bytes.c
CHANGED
|
@@ -24,6 +24,20 @@
|
|
|
24
24
|
#include <constants.h>
|
|
25
25
|
|
|
26
26
|
VALUE force_binary_encoding(VALUE buffer) {
|
|
27
|
+
if (RB_TYPE_P(buffer, T_STRING)) {
|
|
28
|
+
if (rb_enc_get_index(buffer) == rb_ascii8bit_encindex()) {
|
|
29
|
+
return buffer;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (RB_OBJ_FROZEN(buffer)) {
|
|
33
|
+
buffer = rb_obj_dup(buffer);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
rb_enc_associate_index(buffer, rb_ascii8bit_encindex());
|
|
37
|
+
|
|
38
|
+
return buffer;
|
|
39
|
+
}
|
|
40
|
+
|
|
27
41
|
return rb_funcall(thrift_bytes_module, force_binary_encoding_id, 1, buffer);
|
|
28
42
|
}
|
|
29
43
|
|