raptor-io 0.0.1

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.
Files changed (91) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +30 -0
  3. data/README.md +51 -0
  4. data/lib/rack/handler/raptor-io.rb +130 -0
  5. data/lib/raptor-io.rb +11 -0
  6. data/lib/raptor-io/error.rb +19 -0
  7. data/lib/raptor-io/protocol.rb +6 -0
  8. data/lib/raptor-io/protocol/error.rb +10 -0
  9. data/lib/raptor-io/protocol/http.rb +34 -0
  10. data/lib/raptor-io/protocol/http/client.rb +685 -0
  11. data/lib/raptor-io/protocol/http/error.rb +16 -0
  12. data/lib/raptor-io/protocol/http/headers.rb +132 -0
  13. data/lib/raptor-io/protocol/http/message.rb +67 -0
  14. data/lib/raptor-io/protocol/http/request.rb +307 -0
  15. data/lib/raptor-io/protocol/http/request/manipulator.rb +117 -0
  16. data/lib/raptor-io/protocol/http/request/manipulators.rb +217 -0
  17. data/lib/raptor-io/protocol/http/request/manipulators/authenticator.rb +110 -0
  18. data/lib/raptor-io/protocol/http/request/manipulators/authenticators/basic.rb +36 -0
  19. data/lib/raptor-io/protocol/http/request/manipulators/authenticators/digest.rb +135 -0
  20. data/lib/raptor-io/protocol/http/request/manipulators/authenticators/negotiate.rb +69 -0
  21. data/lib/raptor-io/protocol/http/request/manipulators/authenticators/ntlm.rb +29 -0
  22. data/lib/raptor-io/protocol/http/request/manipulators/redirect_follower.rb +65 -0
  23. data/lib/raptor-io/protocol/http/response.rb +166 -0
  24. data/lib/raptor-io/protocol/http/server.rb +446 -0
  25. data/lib/raptor-io/ruby.rb +4 -0
  26. data/lib/raptor-io/ruby/hash.rb +24 -0
  27. data/lib/raptor-io/ruby/ipaddr.rb +15 -0
  28. data/lib/raptor-io/ruby/openssl.rb +23 -0
  29. data/lib/raptor-io/ruby/string.rb +27 -0
  30. data/lib/raptor-io/socket.rb +175 -0
  31. data/lib/raptor-io/socket/comm.rb +143 -0
  32. data/lib/raptor-io/socket/comm/local.rb +94 -0
  33. data/lib/raptor-io/socket/comm/sapni.rb +75 -0
  34. data/lib/raptor-io/socket/comm/socks.rb +237 -0
  35. data/lib/raptor-io/socket/comm_chain.rb +30 -0
  36. data/lib/raptor-io/socket/error.rb +45 -0
  37. data/lib/raptor-io/socket/switch_board.rb +183 -0
  38. data/lib/raptor-io/socket/switch_board/route.rb +42 -0
  39. data/lib/raptor-io/socket/tcp.rb +231 -0
  40. data/lib/raptor-io/socket/tcp/ssl.rb +77 -0
  41. data/lib/raptor-io/socket/tcp_server.rb +16 -0
  42. data/lib/raptor-io/socket/tcp_server/ssl.rb +52 -0
  43. data/lib/raptor-io/socket/udp.rb +0 -0
  44. data/lib/raptor-io/version.rb +6 -0
  45. data/lib/tasks/yard.rake +26 -0
  46. data/spec/rack/handler/raptor_spec.rb +140 -0
  47. data/spec/raptor-io/protocol/http/client_spec.rb +671 -0
  48. data/spec/raptor-io/protocol/http/headers_spec.rb +189 -0
  49. data/spec/raptor-io/protocol/http/message_spec.rb +5 -0
  50. data/spec/raptor-io/protocol/http/request/manipulators/authenticator_spec.rb +193 -0
  51. data/spec/raptor-io/protocol/http/request/manipulators/authenticators/basic_spec.rb +32 -0
  52. data/spec/raptor-io/protocol/http/request/manipulators/authenticators/digest_spec.rb +76 -0
  53. data/spec/raptor-io/protocol/http/request/manipulators/authenticators/negotiate_spec.rb +52 -0
  54. data/spec/raptor-io/protocol/http/request/manipulators/authenticators/ntlm_spec.rb +37 -0
  55. data/spec/raptor-io/protocol/http/request/manipulators/redirect_follower_spec.rb +51 -0
  56. data/spec/raptor-io/protocol/http/request/manipulators_spec.rb +202 -0
  57. data/spec/raptor-io/protocol/http/request_spec.rb +965 -0
  58. data/spec/raptor-io/protocol/http/response_spec.rb +236 -0
  59. data/spec/raptor-io/protocol/http/server_spec.rb +345 -0
  60. data/spec/raptor-io/ruby/hash_spec.rb +20 -0
  61. data/spec/raptor-io/ruby/string_spec.rb +20 -0
  62. data/spec/raptor-io/socket/comm/local_spec.rb +50 -0
  63. data/spec/raptor-io/socket/switch_board/route_spec.rb +49 -0
  64. data/spec/raptor-io/socket/switch_board_spec.rb +87 -0
  65. data/spec/raptor-io/socket/tcp/ssl_spec.rb +18 -0
  66. data/spec/raptor-io/socket/tcp_server/ssl_spec.rb +59 -0
  67. data/spec/raptor-io/socket/tcp_server_spec.rb +19 -0
  68. data/spec/raptor-io/socket/tcp_spec.rb +14 -0
  69. data/spec/raptor-io/socket_spec.rb +16 -0
  70. data/spec/raptor-io/version_spec.rb +10 -0
  71. data/spec/spec_helper.rb +56 -0
  72. data/spec/support/fixtures/raptor/protocol/http/request/manipulators/manifoolators/fooer.rb +25 -0
  73. data/spec/support/fixtures/raptor/protocol/http/request/manipulators/niccolo_machiavelli.rb +20 -0
  74. data/spec/support/fixtures/raptor/protocol/http/request/manipulators/options_validator.rb +28 -0
  75. data/spec/support/fixtures/raptor/socket/ssl_server.crt +18 -0
  76. data/spec/support/fixtures/raptor/socket/ssl_server.key +15 -0
  77. data/spec/support/lib/path_helpers.rb +11 -0
  78. data/spec/support/lib/webserver_option_parser.rb +26 -0
  79. data/spec/support/lib/webservers.rb +120 -0
  80. data/spec/support/shared/contexts/with_ssl_server.rb +70 -0
  81. data/spec/support/shared/contexts/with_tcp_server.rb +58 -0
  82. data/spec/support/shared/examples/raptor/comm_examples.rb +26 -0
  83. data/spec/support/shared/examples/raptor/protocols/http/message.rb +106 -0
  84. data/spec/support/shared/examples/raptor/socket_examples.rb +135 -0
  85. data/spec/support/webservers/raptor/protocols/http/client.rb +100 -0
  86. data/spec/support/webservers/raptor/protocols/http/client_close_connection.rb +29 -0
  87. data/spec/support/webservers/raptor/protocols/http/client_https.rb +43 -0
  88. data/spec/support/webservers/raptor/protocols/http/request/manipulators/authenticators/basic.rb +9 -0
  89. data/spec/support/webservers/raptor/protocols/http/request/manipulators/authenticators/digest.rb +22 -0
  90. data/spec/support/webservers/raptor/protocols/http/request/manipulators/redirect_follower.rb +11 -0
  91. metadata +336 -0
@@ -0,0 +1,15 @@
1
+ require 'ipaddr'
2
+
3
+ class IPAddr
4
+
5
+ # @param [String, IPAddr] parse_me Object to parse.
6
+ # @return [IPAddr]
7
+ def self.parse(parse_me)
8
+ if parse_me.kind_of?(IPAddr)
9
+ parse_me
10
+ else
11
+ IPAddr.new(parse_me)
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,23 @@
1
+ require 'openssl'
2
+
3
+ class OpenSSL::SSL::SSLServer
4
+ # Guard this in case stdlib ever implements it
5
+ unless method_defined?(:accept_nonblock)
6
+ # Non-blocking version of accept, stolen directly from the blocking
7
+ # version, OpenSSL::SSL::SSLServer#accept.
8
+ def accept_nonblock
9
+ sock = @svr.accept_nonblock
10
+
11
+ begin
12
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx)
13
+ ssl.sync_close = true
14
+ ssl.accept if @start_immediately
15
+ ssl
16
+ rescue OpenSSL::SSL::SSLError => ex
17
+ sock.close
18
+ raise ex
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,27 @@
1
+ class String
2
+
3
+ # @return [String] `self` with 8-bit unsigned characters.
4
+ def repack
5
+ unpack( 'C*' ).pack( 'C*' )
6
+ end
7
+
8
+ # Forces `self` to UTF-8 and replaces invalid characters.
9
+ def force_utf8!
10
+ force_encoding( 'utf-8' )
11
+ encode!( 'utf-16be', invalid: :replace, undef: :replace ).encode( 'utf-8' )
12
+ end
13
+
14
+ # @return [String] Copy of `self`, {#force_utf8! forced to UTF-8}.
15
+ def force_utf8
16
+ dup.force_utf8!
17
+ end
18
+
19
+ # @return [Bool]
20
+ # `true` if `self` is binary, `false` if regular text.
21
+ def binary?
22
+ encoding == Encoding::ASCII_8BIT ||
23
+ index( "\x00" ) ||
24
+ count( "\x00-\x7F", "^ -~\t\r\n").fdiv( length ) > 0.3
25
+ end
26
+
27
+ end
@@ -0,0 +1,175 @@
1
+ require 'forwardable'
2
+ require 'raptor-io/ruby'
3
+
4
+ # A basic class for specific transports to inherit from. Analogous to
5
+ # stdlib's BasicSocket
6
+ class RaptorIO::Socket
7
+ extend Forwardable
8
+
9
+ require 'raptor-io/socket/error'
10
+ require 'raptor-io/socket/switch_board'
11
+ require 'raptor-io/socket/tcp'
12
+ require 'raptor-io/socket/tcp/ssl'
13
+ require 'raptor-io/socket/tcp_server'
14
+ require 'raptor-io/socket/tcp_server/ssl'
15
+
16
+ # Like IO.select, but smarter
17
+ #
18
+ # OpenSSL does its own buffering which can result in a consumed TCP
19
+ # buffer, leading `IO.select` to think that the SSLSocket has no more
20
+ # data to provide, when that's not the case, effectively making
21
+ # `IO.select` block forever, even though the SSLSocket's buffer has
22
+ # not yet been consumed.
23
+ #
24
+ # We work around this by attempting a non-blocking read of one byte on
25
+ # each of the `read_array`, and putting the byte back with
26
+ # `Socket#ungetc` if it worked, or running it through the the real
27
+ # `IO.select` if it doesn't.
28
+ #
29
+ # @see http://bugs.ruby-lang.org/issues/8875
30
+ # @see http://jira.codehaus.org/browse/JRUBY-6874
31
+ # @param read_array [Array] (see IO.select)
32
+ # @param write_array [Array] (see IO.select)
33
+ # @param error_array [Array] (see IO.select)
34
+ # @param timeout [Fixnum,nil] (see IO.select)
35
+ #
36
+ # @return [Array] An Array containing three arrays of IO objects that
37
+ # are ready for reading, ready for writing, or have pending errors,
38
+ # respectively.
39
+ # @return [nil] If optional `timeout` is given and `timeout` seconds
40
+ # elapse before any data is available
41
+ def self.select(read_array=[], write_array=[], error_array=[], timeout=nil)
42
+ read_array ||= []
43
+ write_array ||= []
44
+ error_array ||= []
45
+
46
+ readers_with_data = []
47
+
48
+ selectable_readers = read_array.dup.delete_if do |reader|
49
+ begin
50
+ # If this socket doesn't have a read_nonblock method, then it's
51
+ # a server of some kind and we have to run it through the real
52
+ # select to see if it can {TCPServer#accept accept}.
53
+ next false unless reader.respond_to? :read_nonblock
54
+
55
+ byte = reader.read_nonblock(1)
56
+ rescue IO::WaitReadable, IO::WaitWritable
57
+ # Then this thing needs to go through the real select to be able
58
+ # to tell if it has data.
59
+ #
60
+ # Note that {IO::WaitWritable} is needed here because OpenSSL
61
+ # sockets can block for writing when calling `read*` because of
62
+ # session renegotiation and the like.
63
+ false
64
+ rescue EOFError
65
+ # Then this thing has an empty read buffer and there's no more
66
+ # on the wire. We mark it as having data so a subsequent
67
+ # read or read_nonblock will raise EOFError appropriately.
68
+ readers_with_data << reader
69
+ true
70
+ else
71
+ # Then this thing has data already in its read buffer and we can
72
+ # skip the real select for it.
73
+ reader.ungetc(byte)
74
+ readers_with_data << reader
75
+ true
76
+ end
77
+ end
78
+
79
+ if readers_with_data.any?
80
+ if selectable_readers.any? || write_array.any? || error_array.any?
81
+ #$stderr.puts(" ----- Selecting readers:")
82
+ #pp selectable_readers
83
+ # Then see if anything has data right now by using a 0 timeout
84
+ r,w,e = IO.select(selectable_readers, write_array, error_array, 0)
85
+
86
+ real = [
87
+ readers_with_data | (r || []),
88
+ w || [],
89
+ e || []
90
+ ]
91
+ else
92
+ # Then there's nothing selectable and we can just return stuff
93
+ # that has buffered data
94
+ real = [ readers_with_data, [], [] ]
95
+ end
96
+ else
97
+ # Then wait the given timeout, regardless of whether the arrays
98
+ # are empty
99
+ real = IO.select(read_array, write_array, error_array, timeout)
100
+ end
101
+
102
+ #$stderr.puts '------ RaptorIO::Socket.select result ------'
103
+ #pp real
104
+ return real
105
+ end
106
+
107
+ class << self
108
+
109
+ # Captures Ruby exceptions and converts them to RaptorIO Errors.
110
+ #
111
+ # @param [Block] block Block to run.
112
+ def translate_errors( &block )
113
+ block.call
114
+ rescue ::Errno::EPIPE, ::Errno::ECONNRESET => e
115
+ raise RaptorIO::Socket::Error::BrokenPipe, e.to_s
116
+ rescue ::Errno::ECONNREFUSED => e
117
+ raise RaptorIO::Socket::Error::ConnectionRefused, e.to_s
118
+ end
119
+
120
+ # Delegates to `::Socket.getaddrinfo`.
121
+ def getaddrinfo( *args )
122
+ begin
123
+ ::Socket.getaddrinfo( *args )
124
+ # OSX raises SocketError.
125
+ rescue ::SocketError, ::Errno::ENOENT => e
126
+ raise RaptorIO::Socket::Error::CouldNotResolve.new( e.to_s )
127
+ end
128
+ end
129
+
130
+ # Delegate to Ruby Socket.
131
+ def method_missing(meth, *args, &block)
132
+ #$stderr.puts("Socket.method_missing(#{meth}, #{args.inspect}")
133
+ if ::Socket.respond_to?(meth)
134
+ translate_errors do
135
+ ::Socket.__send__(meth, *args, &block)
136
+ end
137
+ else
138
+ super
139
+ end
140
+ end
141
+
142
+ def respond_to_missing?(meth, include_private=false)
143
+ ::Socket.respond_to?(meth, include_private)
144
+ end
145
+ end
146
+
147
+ # Options for this socket.
148
+ #
149
+ # @return [Hash<Symbol,Object>]
150
+ attr_accessor :options
151
+
152
+ # @!method to_io
153
+ # Used by Kernel.select
154
+ # @return [IO]
155
+ def_delegator :@socket, :to_io, :to_io
156
+
157
+ # @param socket [IO] An already-connected socket.
158
+ # @param options [Hash] Options (see {#options}).
159
+ def initialize( socket, options = {} )
160
+ @socket = socket
161
+ @options = options
162
+ end
163
+
164
+ # @!method closed?
165
+ def_delegator :@socket, :closed?, :closed?
166
+
167
+ # @!method close
168
+ def_delegator :@socket, :close, :close
169
+
170
+ # Whether this socket is an SSL stream.
171
+ def ssl?
172
+ false
173
+ end
174
+
175
+ end
@@ -0,0 +1,143 @@
1
+ # -*- coding: binary -*-
2
+ require 'raptor-io/socket'
3
+ require 'ipaddr'
4
+
5
+ ###
6
+ #
7
+ # Provides the basic interface that a derived class must implement
8
+ # in order to be a routable socket creator.
9
+ #
10
+ # See {RaptorIO::Socket::Comm::Local} for an implementation using sockets
11
+ # created with standard Ruby Socket classes.
12
+ #
13
+ # Subclasses must implement the following methods:
14
+ #
15
+ # * `resolve`
16
+ # * `create_tcp`
17
+ # * `create_tcp_server`
18
+ # * `create_udp`
19
+ # * `create_udp_server`
20
+ # * `support_ipv6?`
21
+ #
22
+ ###
23
+ class RaptorIO::Socket::Comm
24
+ require 'raptor-io/socket/comm/local'
25
+ require 'raptor-io/socket/comm/socks'
26
+ require 'raptor-io/socket/comm/sapni'
27
+
28
+ # @param uri [URI]
29
+ def self.from_uri(uri, opts = {})
30
+ raise ArgumentError unless uri.kind_of? URI
31
+
32
+ prev_comm = opts[:prev_comm] || RaptorIO::Socket::Comm::Local.new
33
+
34
+ comm = case uri.scheme.downcase
35
+ when "sapni"
36
+ uri.port ||= 3299
37
+ RaptorIO::Socket::Comm::SAPNI.new(
38
+ sap_host: uri.host,
39
+ sap_port: uri.port,
40
+ sap_comm: prev_comm,
41
+ )
42
+ when "socks"
43
+ uri.port ||= 1080
44
+ RaptorIO::Socket::Comm::SOCKS.new(
45
+ socks_host: uri.host,
46
+ socks_port: uri.port,
47
+ socks_comm: prev_comm,
48
+ )
49
+ end
50
+
51
+ comm
52
+ end
53
+
54
+ # Creates a socket on this Comm based on the supplied uniform
55
+ # parameters.
56
+ #
57
+ # @option options :switch_board [SwitchBoard]
58
+ # @option options :port [Fixnum] Optional based on proto
59
+ # @option options :protocol [Symbol]
60
+ # * `:tcp`
61
+ # * `:udp`
62
+ #
63
+ # @return [RaptorIO::Socket]
64
+ def create( options )
65
+ options = options.dup
66
+ options[:peer_host] = IPAddr.parse(options[:peer_host])
67
+
68
+ case options.delete(:protocol)
69
+ when :tcp
70
+ options[:server] ? create_tcp_server(options) : create_tcp(options)
71
+
72
+ when :udp
73
+ options[:server] ? create_udp_server(options) : create_udp(options)
74
+ end
75
+ end
76
+
77
+ # Resolves a hostname to an IP address using this comm.
78
+ #
79
+ # @abstract
80
+ #
81
+ # @param [String] hostname
82
+ def resolve( hostname )
83
+ raise NotImplementedError
84
+ end
85
+
86
+ # Resolves an IP address to a hostname using this comm.
87
+ #
88
+ # @abstract
89
+ #
90
+ # @param ip_address [String]
91
+ def reverse_resolve( ip_address )
92
+ raise NotImplementedError
93
+ end
94
+
95
+ # Connect to a host over TCP.
96
+ #
97
+ # @abstract
98
+ #
99
+ # @option options :peer_host [String,IPAddr]
100
+ # @option options :peer_port [Fixnum]
101
+ # @option options :local_host [String,IPAddr]
102
+ # @option options :local_port [Fixnum]
103
+ # @return [RaptorIO::Socket::TCP]
104
+ def create_tcp(options)
105
+ raise NotImplementedError
106
+ end
107
+
108
+ # Create a UDP socket bound to the given :peer_host
109
+ #
110
+ # @abstract
111
+ #
112
+ # @option options :peer_host [String,IPAddr]
113
+ # @option options :peer_port [Fixnum]
114
+ # @option options :local_host [String,IPAddr]
115
+ # @option options :local_port [Fixnum]
116
+ def create_udp(options)
117
+ raise NotImplementedError
118
+ end
119
+
120
+ # Create a TCP server listening on :local_port
121
+ #
122
+ # @abstract
123
+ #
124
+ # @option options :local_host [String,IPAddr]
125
+ # @option options :local_port [Fixnum]
126
+ # @option options :ssl_context [OpenSSL::SSL::Context]
127
+ def create_tcp_server(options)
128
+ raise NotImplementedError
129
+ end
130
+
131
+ # Create a UDP server listening on :local_port
132
+ #
133
+ # @abstract
134
+ #
135
+ # @option options :local_host [String,IPAddr]
136
+ # @option options :local_port [Fixnum]
137
+ def create_udp_server(options)
138
+ raise NotImplementedError
139
+ end
140
+
141
+
142
+ end
143
+
@@ -0,0 +1,94 @@
1
+ # -*- coding: binary -*-
2
+ require 'timeout'
3
+ require 'socket'
4
+ require 'resolv'
5
+
6
+ # Local communication using Ruby `::Socket`s
7
+ class RaptorIO::Socket::Comm::Local < RaptorIO::Socket::Comm
8
+
9
+ # Determine whether we support IPv6
10
+ #
11
+ # We attempt to discover this by creating an unbound UDP socket with
12
+ # the AF_INET6 address family
13
+ def support_ipv6?
14
+ return @supports_ipv6 unless @supports_ipv6.nil?
15
+
16
+ @supports_ipv6 = false
17
+
18
+ if ::Socket.const_defined?('AF_INET6')
19
+ begin
20
+ ::Socket.new(::Socket::AF_INET6, ::Socket::SOCK_DGRAM, ::Socket::IPPROTO_UDP).close
21
+ @supports_ipv6 = true
22
+ rescue
23
+ end
24
+ end
25
+
26
+ @supports_ipv6
27
+ end
28
+
29
+ # Resolves a hostname to an IP address using this comm.
30
+ #
31
+ # @param hostname [String]
32
+ def resolve( hostname )
33
+ ::Resolv.getaddress hostname
34
+ end
35
+
36
+ # Resolves an IP address to a hostname using this comm.
37
+ #
38
+ # @param [String] ip_address
39
+ def reverse_resolve( ip_address )
40
+ ::Resolv.getname ip_address
41
+ end
42
+
43
+ # Connect to `:peer_host`
44
+ #
45
+ # @option (see Comm#create_tcp)
46
+ # @return [Socket::TCP]
47
+ # @raise [RaptorIO::Socket::Error::ConnectTimeout]
48
+ def create_tcp( options )
49
+ phost = IPAddr.parse( options[:peer_host] )
50
+
51
+ # Passing an explicit ::Socket::IPPROTO_TCP is broken on jruby
52
+ # See https://github.com/jruby/jruby/issues/785
53
+ socket = ::Socket.new(phost.family, ::Socket::SOCK_STREAM, 0)
54
+ socket.do_not_reverse_lookup = true
55
+
56
+ if options[:local_port] || options[:local_host]
57
+ socket.bind(::Socket.pack_sockaddr_in(options[:local_port], options[:local_host]))
58
+ end
59
+
60
+ begin
61
+ socket.connect_nonblock(::Socket.pack_sockaddr_in(options[:peer_port], phost.to_s))
62
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET
63
+ raise RaptorIO::Socket::Error::ConnectionRefused
64
+ rescue Errno::EINPROGRESS
65
+ # This should almost always be raised with a call to
66
+ # connect_nonblock. When the socket finishes connecting it
67
+ # becomes available for writing.
68
+ res = select(nil, [socket], nil, options[:connect_timeout] || 2)
69
+ if res.nil?
70
+ raise RaptorIO::Socket::Error::ConnectionTimeout
71
+ end
72
+ end
73
+
74
+ if options[:ssl_context]
75
+ RaptorIO::Socket::TCP::SSL.new(socket, options)
76
+ else
77
+ RaptorIO::Socket::TCP.new(socket, options)
78
+ end
79
+ end
80
+
81
+ # Listen locally on `:local_port`
82
+ #
83
+ # @option (see Comm#create_tcp_server)
84
+ def create_tcp_server( options )
85
+ socket = TCPServer.new( options[:local_host], options[:local_port] )
86
+
87
+ if (options[:context] = options.delete(:ssl_context))
88
+ RaptorIO::Socket::TCPServer::SSL.new( socket, options )
89
+ else
90
+ RaptorIO::Socket::TCPServer.new( socket, options )
91
+ end
92
+ end
93
+
94
+ end