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
|
@@ -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,23 +8,23 @@
|
|
|
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
|
|
16
17
|
# KIND, either express or implied. See the License for the
|
|
17
18
|
# specific language governing permissions and limitations
|
|
18
19
|
# under the License.
|
|
19
|
-
#
|
|
20
|
+
#
|
|
20
21
|
|
|
21
22
|
require 'socket'
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
class ServerSocket < BaseServerTransport
|
|
25
|
-
# call-seq: initialize(host = nil, port)
|
|
26
|
-
def initialize(host_or_port, port = nil)
|
|
26
|
+
# call-seq: initialize(host = nil, port, client_timeout: DEFAULT_CLIENT_TIMEOUT)
|
|
27
|
+
def initialize(host_or_port, port = nil, client_timeout: DEFAULT_CLIENT_TIMEOUT)
|
|
27
28
|
if port
|
|
28
29
|
@host = host_or_port
|
|
29
30
|
@port = port
|
|
@@ -31,10 +32,11 @@ module Thrift
|
|
|
31
32
|
@host = nil
|
|
32
33
|
@port = host_or_port
|
|
33
34
|
end
|
|
35
|
+
@client_timeout = client_timeout
|
|
34
36
|
@handle = nil
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
attr_reader :handle
|
|
39
|
+
attr_reader :handle, :client_timeout
|
|
38
40
|
|
|
39
41
|
def listen
|
|
40
42
|
@handle = TCPServer.new(@host, @port)
|
|
@@ -43,7 +45,9 @@ module Thrift
|
|
|
43
45
|
def accept
|
|
44
46
|
unless @handle.nil?
|
|
45
47
|
sock = @handle.accept
|
|
48
|
+
sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
|
|
46
49
|
trans = Socket.new
|
|
50
|
+
trans.timeout = @client_timeout
|
|
47
51
|
trans.handle = sock
|
|
48
52
|
trans
|
|
49
53
|
end
|
|
@@ -58,7 +62,9 @@ module Thrift
|
|
|
58
62
|
@handle.nil? or @handle.closed?
|
|
59
63
|
end
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
def to_io
|
|
66
|
+
@handle&.to_io || raise(IOError, 'closed stream')
|
|
67
|
+
end
|
|
62
68
|
|
|
63
69
|
def to_s
|
|
64
70
|
"socket(#{@host}:#{@port})"
|
|
@@ -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,22 +8,22 @@
|
|
|
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
|
|
16
17
|
# KIND, either express or implied. See the License for the
|
|
17
18
|
# specific language governing permissions and limitations
|
|
18
19
|
# under the License.
|
|
19
|
-
#
|
|
20
|
+
#
|
|
20
21
|
|
|
21
22
|
require 'socket'
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
class Socket < BaseTransport
|
|
25
|
-
def initialize(host='localhost', port=9090, timeout=nil)
|
|
26
|
+
def initialize(host = 'localhost', port = 9090, timeout = nil)
|
|
26
27
|
@host = host
|
|
27
28
|
@port = port
|
|
28
29
|
@timeout = timeout
|
|
@@ -33,111 +34,176 @@ module Thrift
|
|
|
33
34
|
attr_accessor :handle, :timeout
|
|
34
35
|
|
|
35
36
|
def open
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
socket = ::Socket.new(addrinfo[4], ::Socket::SOCK_STREAM, 0)
|
|
39
|
-
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
|
|
40
|
-
sockaddr = ::Socket.sockaddr_in(addrinfo[1], addrinfo[3])
|
|
41
|
-
begin
|
|
42
|
-
socket.connect_nonblock(sockaddr)
|
|
43
|
-
rescue Errno::EINPROGRESS
|
|
44
|
-
unless IO.select(nil, [ socket ], nil, @timeout)
|
|
45
|
-
next
|
|
46
|
-
end
|
|
47
|
-
begin
|
|
48
|
-
socket.connect_nonblock(sockaddr)
|
|
49
|
-
rescue Errno::EISCONN
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
return @handle = socket
|
|
53
|
-
rescue StandardError => e
|
|
54
|
-
next
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}")
|
|
37
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout unless @timeout.nil? || @timeout == 0
|
|
38
|
+
@handle = connect_socket(deadline)
|
|
58
39
|
end
|
|
59
40
|
|
|
60
41
|
def open?
|
|
61
|
-
!@handle.nil?
|
|
42
|
+
!@handle.nil? && !@handle.closed?
|
|
62
43
|
end
|
|
63
44
|
|
|
64
45
|
def write(str)
|
|
65
|
-
raise
|
|
46
|
+
raise TransportException.new(TransportException::NOT_OPEN, "closed stream") unless open?
|
|
66
47
|
str = Bytes.force_binary_encoding(str)
|
|
67
48
|
begin
|
|
68
|
-
if @timeout.nil?
|
|
49
|
+
if @timeout.nil? || @timeout == 0
|
|
69
50
|
@handle.write(str)
|
|
70
51
|
else
|
|
52
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout
|
|
71
53
|
len = 0
|
|
72
|
-
|
|
73
|
-
while
|
|
74
|
-
|
|
75
|
-
if wr and not wr.empty?
|
|
54
|
+
|
|
55
|
+
while len < str.length
|
|
56
|
+
begin
|
|
76
57
|
len += @handle.write_nonblock(str[len..-1])
|
|
77
|
-
|
|
58
|
+
rescue IO::WaitWritable
|
|
59
|
+
wait_for(:write, deadline, str.length)
|
|
60
|
+
rescue IO::WaitReadable
|
|
61
|
+
wait_for(:read, deadline, str.length)
|
|
78
62
|
end
|
|
79
63
|
end
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
else
|
|
83
|
-
len
|
|
84
|
-
end
|
|
64
|
+
|
|
65
|
+
len
|
|
85
66
|
end
|
|
86
67
|
rescue TransportException => e
|
|
87
68
|
# pass this on
|
|
88
69
|
raise e
|
|
89
70
|
rescue StandardError => e
|
|
90
|
-
@handle
|
|
71
|
+
close_socket(@handle)
|
|
91
72
|
@handle = nil
|
|
92
73
|
raise TransportException.new(TransportException::NOT_OPEN, e.message)
|
|
93
74
|
end
|
|
94
75
|
end
|
|
95
76
|
|
|
96
77
|
def read(sz)
|
|
97
|
-
raise
|
|
78
|
+
raise TransportException.new(TransportException::NOT_OPEN, "closed stream") unless open?
|
|
98
79
|
|
|
99
80
|
begin
|
|
100
|
-
if @timeout.nil?
|
|
81
|
+
if @timeout.nil? || @timeout == 0
|
|
101
82
|
data = @handle.readpartial(sz)
|
|
102
83
|
else
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out reading #{sz} bytes from #{@desc}")
|
|
114
|
-
else
|
|
115
|
-
data = @handle.readpartial(sz)
|
|
84
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout
|
|
85
|
+
|
|
86
|
+
data = loop do
|
|
87
|
+
begin
|
|
88
|
+
break @handle.read_nonblock(sz)
|
|
89
|
+
rescue IO::WaitReadable
|
|
90
|
+
wait_for(:read, deadline, sz)
|
|
91
|
+
rescue IO::WaitWritable
|
|
92
|
+
wait_for(:write, deadline, sz)
|
|
93
|
+
end
|
|
116
94
|
end
|
|
117
95
|
end
|
|
118
96
|
rescue TransportException => e
|
|
119
97
|
# don't let this get caught by the StandardError handler
|
|
120
98
|
raise e
|
|
121
99
|
rescue StandardError => e
|
|
122
|
-
@handle
|
|
100
|
+
close_socket(@handle)
|
|
123
101
|
@handle = nil
|
|
124
102
|
raise TransportException.new(TransportException::NOT_OPEN, e.message)
|
|
125
103
|
end
|
|
126
|
-
if (data.nil?
|
|
104
|
+
if (data.nil? || data.length == 0)
|
|
127
105
|
raise TransportException.new(TransportException::UNKNOWN, "Socket: Could not read #{sz} bytes from #{@desc}")
|
|
128
106
|
end
|
|
129
107
|
data
|
|
130
108
|
end
|
|
131
109
|
|
|
132
110
|
def close
|
|
133
|
-
@handle
|
|
111
|
+
close_socket(@handle)
|
|
134
112
|
@handle = nil
|
|
135
113
|
end
|
|
136
114
|
|
|
137
|
-
|
|
115
|
+
def to_io
|
|
116
|
+
@handle&.to_io || raise(IOError, 'closed stream')
|
|
117
|
+
end
|
|
138
118
|
|
|
139
119
|
def to_s
|
|
140
120
|
"socket(#{@host}:#{@port})"
|
|
141
121
|
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
def connect_socket(deadline)
|
|
126
|
+
last_error = nil
|
|
127
|
+
connected_socket = nil
|
|
128
|
+
|
|
129
|
+
Addrinfo.foreach(@host, @port, nil, :STREAM) do |addrinfo|
|
|
130
|
+
socket = nil
|
|
131
|
+
|
|
132
|
+
begin
|
|
133
|
+
socket = if deadline
|
|
134
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
135
|
+
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out opening connection to #{@desc}") if remaining <= 0
|
|
136
|
+
|
|
137
|
+
addrinfo.connect(timeout: remaining)
|
|
138
|
+
else
|
|
139
|
+
addrinfo.connect
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
|
|
143
|
+
connected_socket = socket
|
|
144
|
+
break
|
|
145
|
+
rescue Errno::ETIMEDOUT => e
|
|
146
|
+
close_socket(socket)
|
|
147
|
+
last_error = e
|
|
148
|
+
rescue TransportException
|
|
149
|
+
close_socket(socket)
|
|
150
|
+
raise
|
|
151
|
+
rescue StandardError => e
|
|
152
|
+
close_socket(socket)
|
|
153
|
+
last_error = e
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return connected_socket if connected_socket
|
|
158
|
+
|
|
159
|
+
if last_error.is_a?(Errno::ETIMEDOUT)
|
|
160
|
+
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out opening connection to #{@desc}")
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if deadline && deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC) <= 0
|
|
164
|
+
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out opening connection to #{@desc}")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}"), cause: last_error
|
|
168
|
+
rescue TransportException
|
|
169
|
+
raise
|
|
170
|
+
rescue StandardError
|
|
171
|
+
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def close_socket(socket)
|
|
175
|
+
return if socket.nil?
|
|
176
|
+
return if socket.respond_to?(:closed?) && socket.closed?
|
|
177
|
+
|
|
178
|
+
socket.close
|
|
179
|
+
rescue StandardError
|
|
180
|
+
nil
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def wait_for(operation, deadline, sz)
|
|
184
|
+
rd_ary, wr_ary = case operation
|
|
185
|
+
when :read
|
|
186
|
+
[[@handle], nil]
|
|
187
|
+
when :write
|
|
188
|
+
[nil, [@handle]]
|
|
189
|
+
else
|
|
190
|
+
raise ArgumentError, "Unknown IO wait operation: #{operation.inspect}"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
loop do
|
|
194
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
195
|
+
if remaining <= 0
|
|
196
|
+
case operation
|
|
197
|
+
when :read
|
|
198
|
+
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out reading #{sz} bytes from #{@desc}")
|
|
199
|
+
when :write
|
|
200
|
+
raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out writing #{sz} bytes to #{@desc}")
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
rd, wr, = IO.select(rd_ary, wr_ary, nil, remaining)
|
|
205
|
+
return if (rd && !rd.empty?) || (wr && !wr.empty?)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
142
208
|
end
|
|
143
209
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -22,8 +23,8 @@ require 'socket'
|
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
class SSLServerSocket < ServerSocket
|
|
25
|
-
def initialize(host_or_port, port = nil, ssl_context = nil)
|
|
26
|
-
super(host_or_port, port)
|
|
26
|
+
def initialize(host_or_port, port = nil, ssl_context = nil, client_timeout: DEFAULT_CLIENT_TIMEOUT)
|
|
27
|
+
super(host_or_port, port, client_timeout: client_timeout)
|
|
27
28
|
@ssl_context = ssl_context
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -33,7 +34,7 @@ module Thrift
|
|
|
33
34
|
socket = TCPServer.new(@host, @port)
|
|
34
35
|
@handle = OpenSSL::SSL::SSLServer.new(socket, @ssl_context)
|
|
35
36
|
end
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
def to_s
|
|
38
39
|
"ssl(#{super.to_s})"
|
|
39
40
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: ascii-8bit
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -17,9 +18,11 @@
|
|
|
17
18
|
# specific language governing permissions and limitations
|
|
18
19
|
# under the License.
|
|
19
20
|
|
|
21
|
+
require 'io/wait'
|
|
22
|
+
|
|
20
23
|
module Thrift
|
|
21
24
|
class SSLSocket < Socket
|
|
22
|
-
def initialize(host='localhost', port=9090, timeout=nil, ssl_context=nil)
|
|
25
|
+
def initialize(host = 'localhost', port = 9090, timeout = nil, ssl_context = nil)
|
|
23
26
|
super(host, port, timeout)
|
|
24
27
|
@ssl_context = ssl_context
|
|
25
28
|
end
|
|
@@ -27,23 +30,52 @@ module Thrift
|
|
|
27
30
|
attr_accessor :ssl_context
|
|
28
31
|
|
|
29
32
|
def open
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + @timeout unless @timeout.nil? || @timeout == 0
|
|
34
|
+
socket = connect_socket(deadline)
|
|
35
|
+
|
|
32
36
|
begin
|
|
33
|
-
@
|
|
37
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, @ssl_context)
|
|
38
|
+
ssl_socket.sync_close = true
|
|
39
|
+
@handle = ssl_socket
|
|
40
|
+
|
|
41
|
+
if deadline
|
|
42
|
+
loop do
|
|
43
|
+
result = @handle.connect_nonblock(exception: false)
|
|
44
|
+
|
|
45
|
+
case result
|
|
46
|
+
when @handle
|
|
47
|
+
break
|
|
48
|
+
when :wait_readable
|
|
49
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
50
|
+
if remaining <= 0 || !@handle.to_io.wait_readable(remaining)
|
|
51
|
+
raise TransportException.new(TransportException::TIMED_OUT, "SSL socket: Timed out establishing session with #{@desc}")
|
|
52
|
+
end
|
|
53
|
+
when :wait_writable
|
|
54
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
55
|
+
if remaining <= 0 || !@handle.to_io.wait_writable(remaining)
|
|
56
|
+
raise TransportException.new(TransportException::TIMED_OUT, "SSL socket: Timed out establishing session with #{@desc}")
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: unexpected SSL connect result #{result.inspect}")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
@handle.connect
|
|
64
|
+
end
|
|
65
|
+
|
|
34
66
|
@handle.post_connection_check(@host)
|
|
35
67
|
@handle
|
|
36
|
-
rescue
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}
|
|
68
|
+
rescue TransportException
|
|
69
|
+
close_socket(@handle)
|
|
70
|
+
@handle = nil
|
|
71
|
+
raise
|
|
72
|
+
rescue StandardError
|
|
73
|
+
close_socket(@handle || socket)
|
|
74
|
+
@handle = nil
|
|
75
|
+
raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}")
|
|
44
76
|
end
|
|
45
77
|
end
|
|
46
|
-
|
|
78
|
+
|
|
47
79
|
def to_s
|
|
48
80
|
"ssl(#{super.to_s})"
|
|
49
81
|
end
|
|
@@ -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,27 +8,29 @@
|
|
|
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
|
|
16
17
|
# KIND, either express or implied. See the License for the
|
|
17
18
|
# specific language governing permissions and limitations
|
|
18
19
|
# under the License.
|
|
19
|
-
#
|
|
20
|
+
#
|
|
20
21
|
|
|
21
22
|
require 'socket'
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
class UNIXServerSocket < BaseServerTransport
|
|
25
|
-
def initialize(path)
|
|
26
|
+
def initialize(path, client_timeout: DEFAULT_CLIENT_TIMEOUT)
|
|
26
27
|
@path = path
|
|
28
|
+
@client_timeout = client_timeout
|
|
27
29
|
@handle = nil
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
attr_accessor :handle
|
|
33
|
+
attr_reader :client_timeout
|
|
31
34
|
|
|
32
35
|
def listen
|
|
33
36
|
@handle = ::UNIXServer.new(@path)
|
|
@@ -37,6 +40,7 @@ module Thrift
|
|
|
37
40
|
unless @handle.nil?
|
|
38
41
|
sock = @handle.accept
|
|
39
42
|
trans = UNIXSocket.new(nil)
|
|
43
|
+
trans.timeout = @client_timeout
|
|
40
44
|
trans.handle = sock
|
|
41
45
|
trans
|
|
42
46
|
end
|
|
@@ -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,22 +8,22 @@
|
|
|
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
|
|
16
17
|
# KIND, either express or implied. See the License for the
|
|
17
18
|
# specific language governing permissions and limitations
|
|
18
19
|
# under the License.
|
|
19
|
-
#
|
|
20
|
+
#
|
|
20
21
|
|
|
21
22
|
require 'socket'
|
|
22
23
|
|
|
23
24
|
module Thrift
|
|
24
25
|
class UNIXSocket < Socket
|
|
25
|
-
def initialize(path, timeout=nil)
|
|
26
|
+
def initialize(path, timeout = nil)
|
|
26
27
|
@path = path
|
|
27
28
|
@timeout = timeout
|
|
28
29
|
@desc = @path # for read()'s error
|
|
@@ -36,7 +37,7 @@ module Thrift
|
|
|
36
37
|
raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}")
|
|
37
38
|
end
|
|
38
39
|
end
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
def to_s
|
|
41
42
|
"domain(#{@path})"
|
|
42
43
|
end
|
data/lib/thrift/types.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
|
require 'set'
|
|
21
22
|
|
|
@@ -34,6 +35,7 @@ module Thrift
|
|
|
34
35
|
MAP = 13
|
|
35
36
|
SET = 14
|
|
36
37
|
LIST = 15
|
|
38
|
+
UUID = 16
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
class << self
|
|
@@ -43,7 +45,7 @@ module Thrift
|
|
|
43
45
|
class TypeError < Exception
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
def self.check_type(value, field, name, skip_nil=true)
|
|
48
|
+
def self.check_type(value, field, name, skip_nil = true)
|
|
47
49
|
return if value.nil? and skip_nil
|
|
48
50
|
klasses = case field[:type]
|
|
49
51
|
when Types::VOID
|
|
@@ -56,6 +58,8 @@ module Thrift
|
|
|
56
58
|
Float
|
|
57
59
|
when Types::STRING
|
|
58
60
|
String
|
|
61
|
+
when Types::UUID
|
|
62
|
+
String
|
|
59
63
|
when Types::STRUCT
|
|
60
64
|
[Struct, Union]
|
|
61
65
|
when Types::MAP
|
|
@@ -70,7 +74,7 @@ module Thrift
|
|
|
70
74
|
# check elements now
|
|
71
75
|
case field[:type]
|
|
72
76
|
when Types::MAP
|
|
73
|
-
value.each_pair do |k,v|
|
|
77
|
+
value.each_pair do |k, v|
|
|
74
78
|
check_type(k, field[:key], "#{name}.key", false)
|
|
75
79
|
check_type(v, field[:value], "#{name}.value", false)
|
|
76
80
|
end
|
data/lib/thrift/union.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,20 +7,20 @@
|
|
|
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 Union
|
|
22
|
-
def initialize(name=nil, value=nil)
|
|
23
|
+
def initialize(name = nil, value = nil)
|
|
23
24
|
if name
|
|
24
25
|
if name.is_a? Hash
|
|
25
26
|
if name.size > 1
|
|
@@ -60,7 +61,9 @@ module Thrift
|
|
|
60
61
|
iprot.read_field_end
|
|
61
62
|
|
|
62
63
|
fname, ftype, fid = iprot.read_field_begin
|
|
63
|
-
|
|
64
|
+
unless (ftype == Types::STOP)
|
|
65
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Too many fields for union")
|
|
66
|
+
end
|
|
64
67
|
|
|
65
68
|
iprot.read_struct_end
|
|
66
69
|
validate
|
|
@@ -73,6 +76,10 @@ module Thrift
|
|
|
73
76
|
fid = self.name_to_id(@setfield.to_s)
|
|
74
77
|
|
|
75
78
|
field_info = struct_fields[fid]
|
|
79
|
+
unless field_info
|
|
80
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "set_field is not valid for this union!")
|
|
81
|
+
end
|
|
82
|
+
|
|
76
83
|
type = field_info[:type]
|
|
77
84
|
if is_container? type
|
|
78
85
|
oprot.write_field_begin(@setfield, type, fid)
|
|
@@ -99,7 +106,7 @@ module Thrift
|
|
|
99
106
|
klass.send :define_method, field_info[:name] do
|
|
100
107
|
if field_info[:name].to_sym == @setfield
|
|
101
108
|
@value
|
|
102
|
-
else
|
|
109
|
+
else
|
|
103
110
|
raise RuntimeError, "#{field_info[:name]} is not union's set field."
|
|
104
111
|
end
|
|
105
112
|
end
|
|
@@ -124,7 +131,7 @@ module Thrift
|
|
|
124
131
|
end
|
|
125
132
|
end
|
|
126
133
|
|
|
127
|
-
# get the symbol that indicates what the currently set field type is.
|
|
134
|
+
# get the symbol that indicates what the currently set field type is.
|
|
128
135
|
def get_set_field
|
|
129
136
|
@setfield
|
|
130
137
|
end
|