raptor-io 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE +30 -0
- data/README.md +51 -0
- data/lib/rack/handler/raptor-io.rb +130 -0
- data/lib/raptor-io.rb +11 -0
- data/lib/raptor-io/error.rb +19 -0
- data/lib/raptor-io/protocol.rb +6 -0
- data/lib/raptor-io/protocol/error.rb +10 -0
- data/lib/raptor-io/protocol/http.rb +34 -0
- data/lib/raptor-io/protocol/http/client.rb +685 -0
- data/lib/raptor-io/protocol/http/error.rb +16 -0
- data/lib/raptor-io/protocol/http/headers.rb +132 -0
- data/lib/raptor-io/protocol/http/message.rb +67 -0
- data/lib/raptor-io/protocol/http/request.rb +307 -0
- data/lib/raptor-io/protocol/http/request/manipulator.rb +117 -0
- data/lib/raptor-io/protocol/http/request/manipulators.rb +217 -0
- data/lib/raptor-io/protocol/http/request/manipulators/authenticator.rb +110 -0
- data/lib/raptor-io/protocol/http/request/manipulators/authenticators/basic.rb +36 -0
- data/lib/raptor-io/protocol/http/request/manipulators/authenticators/digest.rb +135 -0
- data/lib/raptor-io/protocol/http/request/manipulators/authenticators/negotiate.rb +69 -0
- data/lib/raptor-io/protocol/http/request/manipulators/authenticators/ntlm.rb +29 -0
- data/lib/raptor-io/protocol/http/request/manipulators/redirect_follower.rb +65 -0
- data/lib/raptor-io/protocol/http/response.rb +166 -0
- data/lib/raptor-io/protocol/http/server.rb +446 -0
- data/lib/raptor-io/ruby.rb +4 -0
- data/lib/raptor-io/ruby/hash.rb +24 -0
- data/lib/raptor-io/ruby/ipaddr.rb +15 -0
- data/lib/raptor-io/ruby/openssl.rb +23 -0
- data/lib/raptor-io/ruby/string.rb +27 -0
- data/lib/raptor-io/socket.rb +175 -0
- data/lib/raptor-io/socket/comm.rb +143 -0
- data/lib/raptor-io/socket/comm/local.rb +94 -0
- data/lib/raptor-io/socket/comm/sapni.rb +75 -0
- data/lib/raptor-io/socket/comm/socks.rb +237 -0
- data/lib/raptor-io/socket/comm_chain.rb +30 -0
- data/lib/raptor-io/socket/error.rb +45 -0
- data/lib/raptor-io/socket/switch_board.rb +183 -0
- data/lib/raptor-io/socket/switch_board/route.rb +42 -0
- data/lib/raptor-io/socket/tcp.rb +231 -0
- data/lib/raptor-io/socket/tcp/ssl.rb +77 -0
- data/lib/raptor-io/socket/tcp_server.rb +16 -0
- data/lib/raptor-io/socket/tcp_server/ssl.rb +52 -0
- data/lib/raptor-io/socket/udp.rb +0 -0
- data/lib/raptor-io/version.rb +6 -0
- data/lib/tasks/yard.rake +26 -0
- data/spec/rack/handler/raptor_spec.rb +140 -0
- data/spec/raptor-io/protocol/http/client_spec.rb +671 -0
- data/spec/raptor-io/protocol/http/headers_spec.rb +189 -0
- data/spec/raptor-io/protocol/http/message_spec.rb +5 -0
- data/spec/raptor-io/protocol/http/request/manipulators/authenticator_spec.rb +193 -0
- data/spec/raptor-io/protocol/http/request/manipulators/authenticators/basic_spec.rb +32 -0
- data/spec/raptor-io/protocol/http/request/manipulators/authenticators/digest_spec.rb +76 -0
- data/spec/raptor-io/protocol/http/request/manipulators/authenticators/negotiate_spec.rb +52 -0
- data/spec/raptor-io/protocol/http/request/manipulators/authenticators/ntlm_spec.rb +37 -0
- data/spec/raptor-io/protocol/http/request/manipulators/redirect_follower_spec.rb +51 -0
- data/spec/raptor-io/protocol/http/request/manipulators_spec.rb +202 -0
- data/spec/raptor-io/protocol/http/request_spec.rb +965 -0
- data/spec/raptor-io/protocol/http/response_spec.rb +236 -0
- data/spec/raptor-io/protocol/http/server_spec.rb +345 -0
- data/spec/raptor-io/ruby/hash_spec.rb +20 -0
- data/spec/raptor-io/ruby/string_spec.rb +20 -0
- data/spec/raptor-io/socket/comm/local_spec.rb +50 -0
- data/spec/raptor-io/socket/switch_board/route_spec.rb +49 -0
- data/spec/raptor-io/socket/switch_board_spec.rb +87 -0
- data/spec/raptor-io/socket/tcp/ssl_spec.rb +18 -0
- data/spec/raptor-io/socket/tcp_server/ssl_spec.rb +59 -0
- data/spec/raptor-io/socket/tcp_server_spec.rb +19 -0
- data/spec/raptor-io/socket/tcp_spec.rb +14 -0
- data/spec/raptor-io/socket_spec.rb +16 -0
- data/spec/raptor-io/version_spec.rb +10 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/support/fixtures/raptor/protocol/http/request/manipulators/manifoolators/fooer.rb +25 -0
- data/spec/support/fixtures/raptor/protocol/http/request/manipulators/niccolo_machiavelli.rb +20 -0
- data/spec/support/fixtures/raptor/protocol/http/request/manipulators/options_validator.rb +28 -0
- data/spec/support/fixtures/raptor/socket/ssl_server.crt +18 -0
- data/spec/support/fixtures/raptor/socket/ssl_server.key +15 -0
- data/spec/support/lib/path_helpers.rb +11 -0
- data/spec/support/lib/webserver_option_parser.rb +26 -0
- data/spec/support/lib/webservers.rb +120 -0
- data/spec/support/shared/contexts/with_ssl_server.rb +70 -0
- data/spec/support/shared/contexts/with_tcp_server.rb +58 -0
- data/spec/support/shared/examples/raptor/comm_examples.rb +26 -0
- data/spec/support/shared/examples/raptor/protocols/http/message.rb +106 -0
- data/spec/support/shared/examples/raptor/socket_examples.rb +135 -0
- data/spec/support/webservers/raptor/protocols/http/client.rb +100 -0
- data/spec/support/webservers/raptor/protocols/http/client_close_connection.rb +29 -0
- data/spec/support/webservers/raptor/protocols/http/client_https.rb +43 -0
- data/spec/support/webservers/raptor/protocols/http/request/manipulators/authenticators/basic.rb +9 -0
- data/spec/support/webservers/raptor/protocols/http/request/manipulators/authenticators/digest.rb +22 -0
- data/spec/support/webservers/raptor/protocols/http/request/manipulators/redirect_follower.rb +11 -0
- metadata +336 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
require 'raptor-io/ruby/ipaddr'
|
3
|
+
|
4
|
+
#
|
5
|
+
# A logical switch board route.
|
6
|
+
#
|
7
|
+
class RaptorIO::Socket::SwitchBoard::Route
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
# @param subnet [String,IPAddr] The network associated with this
|
11
|
+
# route. If specified as a String, must be parseable by IPAddr.new
|
12
|
+
# @param netmask [String,IPAddr] `subnet`'s netmask. If specified as
|
13
|
+
# a String, must be parseable by IPAddr.new
|
14
|
+
# @param comm [Comm] The endpoint where sockets for this route
|
15
|
+
# should be created.
|
16
|
+
def initialize(subnet, netmask, comm)
|
17
|
+
self.netmask = IPAddr.parse(netmask)
|
18
|
+
self.subnet = IPAddr.parse(subnet).mask netmask.to_s
|
19
|
+
self.comm = comm
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# For direct equality, make sure all the attributes are the same
|
24
|
+
#
|
25
|
+
def ==(other)
|
26
|
+
return false unless other.kind_of? RaptorIO::Socket::SwitchBoard::Route
|
27
|
+
netmask == other.netmask && subnet == other.subnet && comm == other.comm
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# For comparison, sort according to netmask.
|
32
|
+
#
|
33
|
+
# This allows {Route routes} to be ordered by specificity
|
34
|
+
#
|
35
|
+
def <=>(other)
|
36
|
+
netmask <=> other.netmask
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :subnet, :netmask, :comm
|
40
|
+
protected
|
41
|
+
attr_writer :subnet, :netmask, :comm
|
42
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# TCP client socket
|
2
|
+
class RaptorIO::Socket::TCP < RaptorIO::Socket
|
3
|
+
|
4
|
+
# Default configuration options.
|
5
|
+
DEFAULT_OPTIONS = {
|
6
|
+
connect_timeout: 5,
|
7
|
+
}
|
8
|
+
|
9
|
+
# Default options for SSL streams connected through this socket.
|
10
|
+
#
|
11
|
+
# @see #to_ssl
|
12
|
+
# @see TCP::SSL
|
13
|
+
DEFAULT_SSL_OPTIONS = {
|
14
|
+
ssl_version: :TLSv1,
|
15
|
+
ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE,
|
16
|
+
}
|
17
|
+
|
18
|
+
# @!attribute socket
|
19
|
+
# The underlying IO for this socket. Usually this is the
|
20
|
+
# `socket` passed to {#initialize}
|
21
|
+
# @return [IO]
|
22
|
+
attr_accessor :socket
|
23
|
+
|
24
|
+
# @param (see Socket#initialize)
|
25
|
+
def initialize(socket, options = {})
|
26
|
+
options = DEFAULT_OPTIONS.merge(options)
|
27
|
+
super
|
28
|
+
@plaintext_socket = @socket = socket
|
29
|
+
end
|
30
|
+
|
31
|
+
# @!method getpeername(string)
|
32
|
+
# Return a Sockaddr struct for the *socket*. Note that this is the
|
33
|
+
# @return [String] Sockaddr data.
|
34
|
+
def_delegator :@plaintext_socket, :getpeername, :getpeername
|
35
|
+
|
36
|
+
# @!method ungetc
|
37
|
+
# Pushes back one character onto the {#socket}'s read buffer. Note
|
38
|
+
# that some streams will *lose data* if this is called with a
|
39
|
+
# `string` larger than one byte or called more than once between
|
40
|
+
# calls to {#read}!
|
41
|
+
#
|
42
|
+
# @param string [String] A single-byte string
|
43
|
+
# @return [nil]
|
44
|
+
def_delegator :@socket, :ungetc, :ungetc
|
45
|
+
|
46
|
+
def remote_address
|
47
|
+
::Addrinfo.new([ "AF_INET", options[:peer_port], options[:peer_host], options[:peer_host] ])
|
48
|
+
end
|
49
|
+
|
50
|
+
# Write `data` to the {#socket}.
|
51
|
+
#
|
52
|
+
# @param data [String,#to_s]
|
53
|
+
# @return [Fixnum]
|
54
|
+
def write(data)
|
55
|
+
begin
|
56
|
+
write_nonblock(data)
|
57
|
+
rescue IO::WaitWritable
|
58
|
+
IO.select(nil, [@socket])
|
59
|
+
retry
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Try to write `data` to the {#socket}.
|
64
|
+
#
|
65
|
+
# @param maxlen [Fixnum]
|
66
|
+
# @return [String]
|
67
|
+
def write_nonblock(data)
|
68
|
+
translate_errors do
|
69
|
+
@socket.write_nonblock(data)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Read exactly `maxlen` bytes from the {#socket}. If fewer than
|
74
|
+
# `maxlen` bytes are available for reading, wait until enough data
|
75
|
+
# is sent.
|
76
|
+
#
|
77
|
+
# @note May block
|
78
|
+
#
|
79
|
+
# @param (see #read_nonblock)
|
80
|
+
# @return (see #read_nonblock)
|
81
|
+
def read(maxlen)
|
82
|
+
buf = ""
|
83
|
+
until 0 == maxlen
|
84
|
+
prev_length = buf.length
|
85
|
+
buf << readpartial(maxlen)
|
86
|
+
maxlen -= buf.length - prev_length
|
87
|
+
end
|
88
|
+
buf
|
89
|
+
end
|
90
|
+
|
91
|
+
# Read at most `maxlen` bytes from the {#socket}.
|
92
|
+
#
|
93
|
+
# @note May block
|
94
|
+
#
|
95
|
+
# @param (see #read_nonblock)
|
96
|
+
# @return (see #read_nonblock)
|
97
|
+
def readpartial(maxlen = nil)
|
98
|
+
begin
|
99
|
+
read_nonblock(maxlen)
|
100
|
+
rescue IO::WaitReadable
|
101
|
+
IO.select([@socket])
|
102
|
+
retry
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Read at most `maxlen` bytes from the {#socket}.
|
107
|
+
#
|
108
|
+
# @param maxlen [Fixnum]
|
109
|
+
# @return [String]
|
110
|
+
def read_nonblock(maxlen = nil)
|
111
|
+
translate_errors do
|
112
|
+
@socket.read_nonblock(maxlen)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Ruby `Socket#gets` accepts:
|
117
|
+
#
|
118
|
+
# * `gets( sep = $/ )`
|
119
|
+
# * `gets( limit = nil )`
|
120
|
+
# * `gets( sep = $/, limit = nil )`
|
121
|
+
#
|
122
|
+
# `OpenSSL::SSL::SSLSocket#gets` however only supports `gets(sep=$/, limit=nil)`.
|
123
|
+
# This hack allows SSLSocket to behave the same as Ruby Socket.
|
124
|
+
#
|
125
|
+
# @note May block
|
126
|
+
def gets(*args)
|
127
|
+
translate_errors do
|
128
|
+
if args.size == 1
|
129
|
+
arg = args.first
|
130
|
+
if arg.is_a?(Numeric)
|
131
|
+
@socket.gets($/, arg)
|
132
|
+
else
|
133
|
+
@socket.gets(arg)
|
134
|
+
end
|
135
|
+
else
|
136
|
+
@socket.gets(*args)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Close this socket. If this socket is an SSL stream, closes both the
|
142
|
+
# SSL stream and the underlying socket
|
143
|
+
#
|
144
|
+
# @return [void]
|
145
|
+
def close
|
146
|
+
begin
|
147
|
+
super
|
148
|
+
ensure
|
149
|
+
if (!@plaintext_socket.closed?)
|
150
|
+
@plaintext_socket.close
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Attempt to turn this into something usable by `IO.select`.
|
156
|
+
#
|
157
|
+
# @return [IO]
|
158
|
+
def to_io
|
159
|
+
IO.try_convert(@socket) || @socket
|
160
|
+
end
|
161
|
+
|
162
|
+
# Whether this socket is encrypted with SSL
|
163
|
+
def ssl?
|
164
|
+
!!(@socket.respond_to?(:context) && @socket.context)
|
165
|
+
end
|
166
|
+
|
167
|
+
# The version of SSL/TLS that was negotiated with the server.
|
168
|
+
#
|
169
|
+
# @return [String] See OpenSSL::SSL::SSLSocket#ssl_version for
|
170
|
+
# possible values
|
171
|
+
# @return [nil] If this socket is not SSL
|
172
|
+
def ssl_version
|
173
|
+
return nil unless ssl?
|
174
|
+
@socket.ssl_version
|
175
|
+
end
|
176
|
+
|
177
|
+
# @return [OpenSSL::SSL::SSLContext]
|
178
|
+
# @return [nil] If this socket is not SSL (see {#ssl?})
|
179
|
+
def ssl_context
|
180
|
+
return nil unless ssl?
|
181
|
+
@socket.context
|
182
|
+
end
|
183
|
+
|
184
|
+
# @note The original socket is replaced by the newly connected
|
185
|
+
# {TCP::SSL} socket
|
186
|
+
#
|
187
|
+
# Starts an SSL/TLS stream over this connection.
|
188
|
+
#
|
189
|
+
# Using this as opposed to directly instantiating {TCP::SSL} allows
|
190
|
+
# you to start a TLS connection after data has already been exchanged
|
191
|
+
# to enable things like `STARTTLS`.
|
192
|
+
#
|
193
|
+
# @note May block
|
194
|
+
#
|
195
|
+
# @param ssl_options [Hash] Options
|
196
|
+
# @option ssl_options :ssl_version [Symbol] (:TLSv1)
|
197
|
+
# @option ssl_options :ssl_verify_mode [Constant] (OpenSSL::SSL::VERIFY_PEER)
|
198
|
+
# Peer verification mode.
|
199
|
+
# @option ssl_config :ssl_context [OpenSSL::SSL::SSLContext] (nil)
|
200
|
+
# SSL context to use.
|
201
|
+
#
|
202
|
+
# @return [RaptorIO::Socket::TCP::SSL] A new Socket with an established
|
203
|
+
# SSL connection
|
204
|
+
def to_ssl(ssl_options = {})
|
205
|
+
if ssl_options[:ssl_context]
|
206
|
+
options[:ssl_context] = ssl_options[:ssl_context]
|
207
|
+
else
|
208
|
+
ssl_options = DEFAULT_SSL_OPTIONS.merge(ssl_options)
|
209
|
+
options[:ssl_context] = OpenSSL::SSL::SSLContext.new.tap do |ctx|
|
210
|
+
ctx.ssl_version = ssl_options[:ssl_version]
|
211
|
+
ctx.verify_mode = ssl_options[:ssl_verify_mode]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
s = RaptorIO::Socket::TCP::SSL.new(@plaintext_socket, options)
|
216
|
+
@socket = s
|
217
|
+
s
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
attr_accessor :plaintext_socket
|
222
|
+
|
223
|
+
def translate_errors(&block)
|
224
|
+
yield
|
225
|
+
rescue Errno::ECONNRESET, Errno::EPIPE
|
226
|
+
raise RaptorIO::Socket::Error::BrokenPipe
|
227
|
+
rescue Errno::ECONNREFUSED
|
228
|
+
raise RaptorIO::Socket::Error::ConnectionRefused
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
# TCP client with SSL encryption.
|
3
|
+
#
|
4
|
+
# @author Tasos Laskos <tasos_laskos@rapid7.com>
|
5
|
+
class RaptorIO::Socket::TCP::SSL < RaptorIO::Socket::TCP
|
6
|
+
|
7
|
+
# Create a new {SSL} from an already-connected
|
8
|
+
# `OpenSSL::SSL::SSLSocket`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# tcp_server = ::TCPServer.new()
|
12
|
+
# ssl_server = OpenSSL::SSL::SSLServer.new(tcp_server)
|
13
|
+
# RaptorIO::Socket::TCP::SSL.from_openssl(ssl_server.accept)
|
14
|
+
#
|
15
|
+
# @see TCPServer::SSL
|
16
|
+
# @param openssl_socket [OpenSSL::SSL::SSLSocket]
|
17
|
+
# @return [SSL]
|
18
|
+
def self.from_openssl(openssl_socket)
|
19
|
+
raptor = self.allocate
|
20
|
+
raptor.__send__(:socket=, openssl_socket)
|
21
|
+
raptor.__send__(:plaintext_socket=, openssl_socket.to_io)
|
22
|
+
raptor.options = {}
|
23
|
+
raptor.options[:ssl_context] = openssl_socket.context
|
24
|
+
|
25
|
+
raptor
|
26
|
+
end
|
27
|
+
|
28
|
+
# @!method ssl_context
|
29
|
+
# The SSL context for this encrypted stream.
|
30
|
+
#
|
31
|
+
# @return [OpenSSL::SSL::Context]
|
32
|
+
def_delegator :@socket, :ssl_context, :context
|
33
|
+
|
34
|
+
# @!method verify_mode
|
35
|
+
# @return [Fixnum] One of the `OpenSSL::SSL::VERIFY_*` constants
|
36
|
+
def_delegator :@socket, :ssl_verify_mode, :verify_mode
|
37
|
+
|
38
|
+
# @!method version
|
39
|
+
# @return [Symbol] SSL version.
|
40
|
+
def_delegator :@socket, :ssl_version, :version
|
41
|
+
|
42
|
+
# @param socket [RaptorIO::Socket]
|
43
|
+
# @param options [Hash] Options
|
44
|
+
# @option (see TCP#to_ssl)
|
45
|
+
def initialize( socket, options = {} )
|
46
|
+
options = DEFAULT_SSL_OPTIONS.merge( options )
|
47
|
+
super
|
48
|
+
|
49
|
+
@context = options[:context] || options[:ssl_context]
|
50
|
+
|
51
|
+
if @context.nil?
|
52
|
+
@context = OpenSSL::SSL::SSLContext.new( options[:ssl_version] )
|
53
|
+
@context.verify_mode = options[:ssl_verify_mode]
|
54
|
+
end
|
55
|
+
|
56
|
+
@socket = OpenSSL::SSL::SSLSocket.new(socket.to_io, @context)
|
57
|
+
begin
|
58
|
+
#$stderr.puts("#{self.class}#initialize connecting")
|
59
|
+
@socket.connect_nonblock
|
60
|
+
rescue IO::WaitReadable, IO::WaitWritable => e
|
61
|
+
#$stderr.puts("Wait*able #{e}, #{options[:connect_timeout].inspect}")
|
62
|
+
if e.kind_of? IO::WaitReadable
|
63
|
+
r,w,_ = IO.select([@socket], nil, nil, options[:connect_timeout])
|
64
|
+
else
|
65
|
+
r,w,_ = IO.select(nil, [@socket], nil, options[:connect_timeout])
|
66
|
+
end
|
67
|
+
|
68
|
+
if r.nil? && w.nil?
|
69
|
+
#$stderr.puts("timeout")
|
70
|
+
raise RaptorIO::Socket::Error::ConnectionTimeout.new(e.to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
retry
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# A listening TCP socket
|
2
|
+
class RaptorIO::Socket::TCPServer < RaptorIO::Socket
|
3
|
+
|
4
|
+
# @!method accept
|
5
|
+
def_delegator :@socket, :accept, :accept
|
6
|
+
|
7
|
+
# @!method accept_nonblock
|
8
|
+
def_delegator :@socket, :accept_nonblock, :accept_nonblock
|
9
|
+
|
10
|
+
# @!method bind
|
11
|
+
def_delegator :@socket, :bind, :bind
|
12
|
+
|
13
|
+
# @!method listen
|
14
|
+
def_delegator :@socket, :listen, :listen
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# TCP server with SSL encryption.
|
2
|
+
#
|
3
|
+
# @author Tasos Laskos <tasos_laskos@rapid7.com>
|
4
|
+
class RaptorIO::Socket::TCPServer::SSL < RaptorIO::Socket::TCPServer
|
5
|
+
|
6
|
+
def initialize( socket, options = {} )
|
7
|
+
#p options[:context].frozen?
|
8
|
+
super
|
9
|
+
#p options[:context].frozen?
|
10
|
+
|
11
|
+
@context = options[:context]
|
12
|
+
if @context.nil?
|
13
|
+
@context = OpenSSL::SSL::SSLContext.new( options[:ssl_version] )
|
14
|
+
@context.verify_mode = options[:verify_mode]
|
15
|
+
end
|
16
|
+
|
17
|
+
@plaintext_socket = socket
|
18
|
+
@socket = OpenSSL::SSL::SSLServer.new( socket, @context )
|
19
|
+
end
|
20
|
+
|
21
|
+
# Accepts a client connection.
|
22
|
+
#
|
23
|
+
# @see Socket::TCP::SSL.from_openssl
|
24
|
+
# @return [RaptorIO::Socket::TCP::SSL]
|
25
|
+
def accept
|
26
|
+
RaptorIO::Socket::TCP::SSL.from_openssl(@socket.accept)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Accepts a client connection without blocking.
|
30
|
+
#
|
31
|
+
# @see Socket::TCP::SSL.from_openssl
|
32
|
+
# @return [RaptorIO::Socket::TCP::SSL]
|
33
|
+
# @raise [IO::WaitWritable]
|
34
|
+
def accept_nonblock
|
35
|
+
RaptorIO::Socket::TCP::SSL.from_openssl(@socket.accept_nonblock)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Close this SSL stream and the underlying socket
|
39
|
+
#
|
40
|
+
# @return [void]
|
41
|
+
def close
|
42
|
+
begin
|
43
|
+
@socket.close
|
44
|
+
ensure
|
45
|
+
if (!@plaintext_socket.closed?)
|
46
|
+
@plaintext_socket.close
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
File without changes
|
data/lib/tasks/yard.rake
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# @note All options not specific to any given rake task should go in the .yardopts file so they are available to both
|
2
|
+
# the below rake tasks and when invoking `yard` from the command line
|
3
|
+
|
4
|
+
if defined? YARD
|
5
|
+
namespace :yard do
|
6
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
7
|
+
# --no-stats here as 'stats' task called after will print fuller stats
|
8
|
+
t.options = ['--no-stats']
|
9
|
+
|
10
|
+
t.after = Proc.new {
|
11
|
+
Rake::Task['yard:stats'].execute
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Shows stats for YARD Documentation including listing undocumented modules, classes, constants, and methods"
|
16
|
+
task :stats => :environment do
|
17
|
+
stats = YARD::CLI::Stats.new
|
18
|
+
stats.run('--compact', '--list-undoc')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @todo Figure out how to just clone description from yard:doc
|
23
|
+
desc "Generate YARD documentation"
|
24
|
+
# allow calling namespace to as a task that goes to default task for namespace
|
25
|
+
task :yard => ['yard:doc']
|
26
|
+
end
|