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