lib/jrpc/transport/socket_tcp.rb in jrpc-1.1.1 vs lib/jrpc/transport/socket_tcp.rb in jrpc-1.1.2
- old
+ new
@@ -1,52 +1,62 @@
module JRPC
module Transport
class SocketTcp < SocketBase
- attr_reader :socket
-
- def initialize(options)
- super
- @socket = build_socket
- end
-
def read(length, timeout = @read_timeout)
received = ''
length_to_read = length
while length_to_read > 0
- io_read, = IO.select([@socket], [], [], timeout)
+ io_read, = IO.select([socket], [], [], timeout)
raise ReadTimeoutError unless io_read
chunk = io_read[0].read_nonblock(length_to_read)
received += chunk
length_to_read -= chunk.bytesize
end
received
+ rescue Errno::EPIPE => e
+ # EPIPE, in this case, means that the data connection was unexpectedly terminated.
+ clear_socket!
+ raise ReadFailedError, "#{e.class} #{e.message}"
end
def write(data, timeout = @write_timeout)
length_written = 0
data_to_write = data
while data_to_write.bytesize > 0
- _, io_write, = IO.select([], [@socket], [], timeout)
+ _, io_write, = IO.select([], [socket], [], timeout)
raise WriteTimeoutError unless io_write
chunk_length = io_write[0].write_nonblock(data_to_write)
length_written += chunk_length
data_to_write = data.byteslice(length_written, data.length)
end
length_written
+ rescue Errno::EPIPE => e
+ # EPIPE, in this case, means that the data connection was unexpectedly terminated.
+ clear_socket!
+ raise WriteFailedError, "#{e.class} #{e.message}"
end
def close
- @socket.close
+ return if @socket.nil?
+ socket.close
end
def closed?
- @socket.closed?
+ @socket.nil? || socket.closed?
end
+ def socket
+ @socket ||= build_socket
+ end
+
private
+ def clear_socket!
+ @socket = nil
+ end
+
def set_timeout_to(socket, type, value)
secs = Integer(value)
u_secs = Integer((value - secs) * 1_000_000)
opt_val = [secs, u_secs].pack('l_2')
socket.setsockopt Socket::SOL_SOCKET, type, opt_val
@@ -62,15 +72,14 @@
def connect_socket
host, port = @server.split(':')
addr = Socket.getaddrinfo(host, nil)
full_addr = Socket.pack_sockaddr_in(port, addr[0][3])
- @socket.connect(full_addr)
+ socket.connect(full_addr)
rescue Errno::EISCONN => _
# already connected
- rescue Errno::ETIMEDOUT => _
- raise ConnectionTimeoutError
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT => e
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::EPIPE => e
+ clear_socket!
raise ConnectionFailedError, "#{e.class} #{e.message}"
end
end
end