lib/dalli/socket.rb in dalli-2.7.11 vs lib/dalli/socket.rb in dalli-3.0.0
- old
+ new
@@ -1,170 +1,95 @@
# frozen_string_literal: true
-require 'rbconfig'
-module Dalli::Server::TCPSocketOptions
- def setsockopts(sock, options)
- sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) if options[:keepalive]
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
- sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
- end
-end
+require 'openssl'
-begin
- require 'kgio'
- puts "Using kgio socket IO" if defined?($TESTING) && $TESTING
-
- class Dalli::Server::KSocket < Kgio::Socket
- attr_accessor :options, :server
-
- def kgio_wait_readable
- IO.select([self], nil, nil, options[:socket_timeout]) || raise(Timeout::Error, "IO timeout")
- end
-
- def kgio_wait_writable
- IO.select(nil, [self], nil, options[:socket_timeout]) || raise(Timeout::Error, "IO timeout")
- end
-
- alias :write :kgio_write
-
- def readfull(count)
- value = String.new('')
- while true
- value << kgio_read!(count - value.bytesize)
- break if value.bytesize == count
- end
- value
- end
-
- def read_available
- value = String.new('')
- while true
- ret = kgio_tryread(8196)
- case ret
- when nil
- raise EOFError, 'end of stream'
- when :wait_readable
- break
- else
- value << ret
- end
- end
- value
- end
- end
-
- class Dalli::Server::KSocket::TCP < Dalli::Server::KSocket
- extend Dalli::Server::TCPSocketOptions
-
- def self.open(host, port, server, options = {})
- addr = Socket.pack_sockaddr_in(port, host)
- sock = start(addr)
- setsockopts(sock, options)
- sock.options = options
- sock.server = server
- sock.kgio_wait_writable
- sock
- rescue Timeout::Error
- sock.close if sock
- raise
- end
- end
-
- class Dalli::Server::KSocket::UNIX < Dalli::Server::KSocket
- def self.open(path, server, options = {})
- addr = Socket.pack_sockaddr_un(path)
- sock = start(addr)
- sock.options = options
- sock.server = server
- sock.kgio_wait_writable
- sock
- rescue Timeout::Error
- sock.close if sock
- raise
- end
- end
-
- if ::Kgio.respond_to?(:wait_readable=)
- ::Kgio.wait_readable = :kgio_wait_readable
- ::Kgio.wait_writable = :kgio_wait_writable
- end
-
-rescue LoadError
-
- puts "Using standard socket IO (#{RUBY_DESCRIPTION})" if defined?($TESTING) && $TESTING
- module Dalli::Server::KSocket
+module Dalli
+ module Socket
module InstanceMethods
+
def readfull(count)
- value = String.new('')
- begin
- while true
- value << read_nonblock(count - value.bytesize)
- break if value.bytesize == count
- end
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
- if IO.select([self], nil, nil, options[:socket_timeout])
- retry
+ value = +""
+ loop do
+ result = read_nonblock(count - value.bytesize, exception: false)
+ if result == :wait_readable
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select([self], nil, nil, options[:socket_timeout])
+ elsif result == :wait_writable
+ raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless IO.select(nil, [self], nil, options[:socket_timeout])
+ elsif result
+ value << result
else
- safe_options = options.reject{|k,v| [:username, :password].include? k}
- raise Timeout::Error, "IO timeout: #{safe_options.inspect}"
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
end
+ break if value.bytesize == count
end
value
end
def read_available
- value = String.new('')
- while true
- begin
- value << read_nonblock(8196)
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ value = +""
+ loop do
+ result = read_nonblock(8196, exception: false)
+ if result == :wait_readable
break
+ elsif result == :wait_writable
+ break
+ elsif result
+ value << result
+ else
+ raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
end
end
value
end
- end
- def self.included(receiver)
- receiver.send(:attr_accessor, :options, :server)
- receiver.send(:include, InstanceMethods)
+ def safe_options
+ options.reject { |k, v| [:username, :password].include? k }
+ end
end
- end
- class Dalli::Server::KSocket::TCP < TCPSocket
- extend Dalli::Server::TCPSocketOptions
- include Dalli::Server::KSocket
-
- def self.open(host, port, server, options = {})
- Timeout.timeout(options[:socket_timeout]) do
- sock = new(host, port)
- setsockopts(sock, options)
- sock.options = {:host => host, :port => port}.merge(options)
- sock.server = server
- sock
+ class SSLSocket < ::OpenSSL::SSL::SSLSocket
+ include Dalli::Socket::InstanceMethods
+ def options
+ io.options
end
end
- end
- if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
- class Dalli::Server::KSocket::UNIX
- def initialize(*args)
- raise Dalli::DalliError, "Unix sockets are not supported on Windows platform."
+ class TCP < TCPSocket
+ include Dalli::Socket::InstanceMethods
+ attr_accessor :options, :server
+
+ def self.open(host, port, server, options = {})
+ Timeout.timeout(options[:socket_timeout]) do
+ sock = new(host, port)
+ sock.options = {host: host, port: port}.merge(options)
+ sock.server = server
+ sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVBUF, options[:rcvbuf]) if options[:rcvbuf]
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDBUF, options[:sndbuf]) if options[:sndbuf]
+
+ return sock unless options[:ssl_context]
+
+ ssl_socket = Dalli::Socket::SSLSocket.new(sock, options[:ssl_context])
+ ssl_socket.hostname = host
+ ssl_socket.sync_close = true
+ ssl_socket.connect
+ ssl_socket
+ end
end
end
- else
- class Dalli::Server::KSocket::UNIX < UNIXSocket
- include Dalli::Server::KSocket
+ class UNIX < UNIXSocket
+ include Dalli::Socket::InstanceMethods
+ attr_accessor :options, :server
+
def self.open(path, server, options = {})
Timeout.timeout(options[:socket_timeout]) do
sock = new(path)
- sock.options = {:path => path}.merge(options)
+ sock.options = {path: path}.merge(options)
sock.server = server
sock
end
end
end
-
end
end