-
Notifications
You must be signed in to change notification settings - Fork 446
/
socket.rb
113 lines (100 loc) · 3.36 KB
/
socket.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# frozen_string_literal: true
require 'openssl'
require 'rbconfig'
module Dalli
module Socket
module InstanceMethods
def readfull(count)
value = +""
loop do
result = read_nonblock(count - value.bytesize, exception: false)
if result == :wait_readable
raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless wait_readable(options[:socket_timeout])
elsif result == :wait_writable
raise Timeout::Error, "IO timeout: #{safe_options.inspect}" unless wait_writable(options[:socket_timeout])
elsif result
value << result
else
raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
end
break if value.bytesize == count
end
value
end
def read_available
value = +""
loop do
result = read_nonblock(8196, exception: false)
if (result == :wait_readable) || (result == :wait_writable)
break
elsif result
value << result
else
raise Errno::ECONNRESET, "Connection reset: #{safe_options.inspect}"
end
end
value
end
def safe_options
options.reject { |k, v| [:username, :password].include? k }
end
end
class SSLSocket < ::OpenSSL::SSL::SSLSocket
include Dalli::Socket::InstanceMethods
def options
io.options
end
unless method_defined?(:wait_readable)
def wait_readable(timeout = nil)
to_io.wait_readable(timeout)
end
end
unless method_defined?(:wait_writable)
def wait_writable(timeout = nil)
to_io.wait_writable(timeout)
end
end
end
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
if RbConfig::CONFIG['host_os'] =~ /mingw|mswin/
class UNIX
def initialize(*_args)
raise Dalli::DalliError, 'Unix sockets are not supported on Windows platform.'
end
end
else
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.server = server
sock
end
end
end
end
end
end