This file is indexed.

/usr/lib/ruby/vendor_ruby/qrack/client.rb is in ruby-bunny 0.7.8-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# encoding: utf-8

begin
  # try loading AMQ::Client::Setttings form the amq client gem, if it has been already loaded
  # this avoids "warning: already initialized constant AMQP_PORTS"
  require "amq/client/settings"
rescue LoadError
  require "qrack/amq-client-url"
end

module Qrack

  class ClientTimeout < Timeout::Error; end
  class ConnectionTimeout < Timeout::Error; end
  class FrameTimeout < Timeout::Error; end

  # Client ancestor class
  class Client

    CONNECT_TIMEOUT = 5.0
    RETRY_DELAY     = 10.0

    attr_reader   :status, :host, :vhost, :port, :logging, :spec, :heartbeat
    attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out, :connecting

    # Temporary hack to make Bunny 0.7 work with port number in AMQP URL.
    # This is not necessary on Bunny 0.8 as it removes support of AMQP 0.8.
    attr_reader :__opts__

    def initialize(connection_string_or_opts = Hash.new, opts = Hash.new)
      opts = case connection_string_or_opts
      when String then
        AMQ::Client::Settings.parse_amqp_url(connection_string_or_opts)
      when Hash then
        connection_string_or_opts
      else
        Hash.new
      end.merge(opts)

      # Temporary hack to make Bunny 0.7 work with port number in AMQP URL.
      # This is not necessary on Bunny 0.8 as it removes support of AMQP 0.8.
      @__opts__ = opts


      @host   = opts[:host] || 'localhost'
      @user   = opts[:user]  || 'guest'
      @pass   = opts[:pass]  || 'guest'
      @vhost  = opts[:vhost] || '/'
      @logfile = opts[:logfile] || nil
      @logging = opts[:logging] || false
      @ssl = opts[:ssl] || false
      @verify_ssl = opts[:verify_ssl].nil? || opts[:verify_ssl]
      @status = :not_connected
      @frame_max = opts[:frame_max] || 131072
      @channel_max = opts[:channel_max] || 0
      @heartbeat = opts[:heartbeat] || 0
      @connect_timeout = opts[:connect_timeout] || CONNECT_TIMEOUT
      @read_write_timeout = opts[:socket_timeout]
      @read_write_timeout = nil if @read_write_timeout == 0
      @disconnect_timeout = @read_write_timeout || @connect_timeout
      @logger = nil
      create_logger if @logging
      @message_in = false
      @message_out = false
      @connecting = false
      @channels ||= []
      # Create channel 0
      @channel = create_channel()
      @exchanges ||= {}
      @queues ||= {}
    end


    # Closes all active communication channels and connection. If an error occurs a @Bunny::ProtocolError@ is raised. If successful, @Client.status@ is set to @:not_connected@.

    # @return [Symbol] @:not_connected@ if successful.
    def close
      return if @socket.nil? || @socket.closed?

      # Close all active channels
      channels.each do |c|
        Bunny::Timer::timeout(@disconnect_timeout) { c.close } if c.open?
      end

      # Close connection to AMQP server
      Bunny::Timer::timeout(@disconnect_timeout) { close_connection }

    rescue Exception
      # http://cheezburger.com/Asset/View/4033311488
    ensure
      # Clear the channels
      @channels = []

      # Create channel 0
      @channel = create_channel()

      # Close TCP Socket
      close_socket
    end

    alias stop close

    def connected?
      status == :connected
    end

    def connecting?
      connecting
    end

    def logging=(bool)
      @logging = bool
      create_logger if @logging
    end

    def next_payload(options = {})
      res = next_frame(options)
      res.payload if res
    end

    alias next_method next_payload

    def read(*args)
      send_command(:read, *args)
      # Got a SIGINT while waiting; give any traps a chance to run
    rescue Errno::EINTR
      retry
    end

  # Checks to see whether or not an undeliverable message has been returned as a result of a publish
  # with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.

  # @param [Hash] opts Options.
  # @option opts [Numeric] :timeout (0.1) The method will wait for a return message until this timeout interval is reached.
  # @return [Hash] @{:header => nil, :payload => :no_return, :return_details => nil}@ if message is not returned before timeout. @{:header, :return_details, :payload}@ if message is returned. @:return_details@ is a hash @{:reply_code, :reply_text, :exchange, :routing_key}@.
    def returned_message(opts = {})

      begin
        frame = next_frame(:timeout => opts[:timeout] || 0.1)
      rescue Qrack::FrameTimeout
        return {:header => nil, :payload => :no_return, :return_details => nil}
      end

      method = frame.payload
      header = next_payload

      # If maximum frame size is smaller than message payload body then message
      # will have a message header and several message bodies
      msg = ''
      while msg.length < header.size
        msg << next_payload
      end

      # Return the message and related info
      {:header => header, :payload => msg, :return_details => method.arguments}
    end

    def switch_channel(chann)
      if (0...channels.size).include? chann
        @channel = channels[chann]
        chann
      else
        raise RuntimeError, "Invalid channel number - #{chann}"
      end
    end

    def write(*args)
      send_command(:write, *args)
    end

    private

    def close_socket(reason=nil)
      # Close the socket. The server is not considered dead.
      @socket.close if @socket and not @socket.closed?
      @socket   = nil
      @status   = :not_connected
    end

    def create_logger
      @logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
      @logger.level = Logger::INFO
      @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
    end

    def send_command(cmd, *args)
      begin
        raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
        if @read_write_timeout
          Bunny::Timer::timeout(@read_write_timeout, Qrack::ClientTimeout) do
            @socket.__send__(cmd, *args)
          end
        else
          @socket.__send__(cmd, *args)
        end
      rescue Errno::EPIPE, Errno::EAGAIN, Qrack::ClientTimeout, IOError => e
        # Ensure we close the socket when we are down to prevent further
        # attempts to write to a closed socket
        close_socket
        raise Bunny::ServerDownError, e.message
      end
    end

    def socket
      return @socket if @socket and (@status == :connected) and not @socket.closed?

      begin
        # Attempt to connect.
        @socket = Bunny::Timer::timeout(@connect_timeout, ConnectionTimeout) do
          TCPSocket.new(host, port)
        end

        if Socket.constants.include?('TCP_NODELAY') || Socket.constants.include?(:TCP_NODELAY)
          @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
        end

        if @ssl
          require 'openssl' unless defined? OpenSSL::SSL
          @socket = OpenSSL::SSL::SSLSocket.new(@socket)
          @socket.sync_close = true
          @socket.connect
          @socket.post_connection_check(host) if @verify_ssl
          @socket
        end
      rescue => e
        @status = :not_connected
        raise Bunny::ServerDownError, e.message
      end

      @socket
    end

  end

end