File: socket.rb

package info (click to toggle)
ruby-bunny 2.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,644 kB
  • sloc: ruby: 10,256; sh: 70; makefile: 8
file content (57 lines) | stat: -rw-r--r-- 1,832 bytes parent folder | download | duplicates (4)
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
require "bunny/cruby/socket"

module Bunny
  module JRuby
    # TCP socket extension that uses Socket#readpartial to avoid excessive CPU
    # burn after some time. See issue #165.
    # @private
    module Socket
      include Bunny::Socket

      def self.open(host, port, options = {})
        socket = ::Socket.tcp(host, port, nil, nil,
                              connect_timeout: options[:connect_timeout])
        if ::Socket.constants.include?('TCP_NODELAY') || ::Socket.constants.include?(:TCP_NODELAY)
          socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
        end
        socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options.fetch(:keepalive, true)
        socket.extend self
        socket.options = { :host => host, :port => port }.merge(options)
        socket
      rescue Errno::ETIMEDOUT
        raise ClientTimeout
      end

      # Reads given number of bytes with an optional timeout
      #
      # @param [Integer] count How many bytes to read
      # @param [Integer] timeout Timeout
      #
      # @return [String] Data read from the socket
      # @api public
      def read_fully(count, timeout = nil)
        value = ''

        begin
          loop do
            value << read_nonblock(count - value.bytesize)
            break if value.bytesize >= count
          end
        rescue EOFError
          # JRuby specific fix via https://github.com/jruby/jruby/issues/1694#issuecomment-54873532
          IO.select([self], nil, nil, timeout)
          retry
        rescue *READ_RETRY_EXCEPTION_CLASSES
          if IO.select([self], nil, nil, timeout)
            retry
          else
            raise Timeout::Error, "IO timeout when reading #{count} bytes"
          end
        end

        value
      end # read_fully

    end
  end
end