amqp-client 1.0.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +2 -2
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +29 -12
- data/CHANGELOG.md +22 -0
- data/Gemfile +4 -0
- data/README.md +62 -27
- data/Rakefile +3 -1
- data/amqp-client.gemspec +1 -1
- data/lib/amqp/client/channel.rb +11 -10
- data/lib/amqp/client/connection.rb +93 -56
- data/lib/amqp/client/{frames.rb → frame_bytes.rb} +34 -36
- data/lib/amqp/client/message.rb +101 -44
- data/lib/amqp/client/properties.rb +143 -76
- data/lib/amqp/client/table.rb +51 -32
- data/lib/amqp/client/version.rb +1 -1
- data/lib/amqp/client.rb +19 -7
- data/sig/amqp-client.rbs +264 -0
- metadata +5 -4
@@ -3,7 +3,7 @@
|
|
3
3
|
require "socket"
|
4
4
|
require "uri"
|
5
5
|
require "openssl"
|
6
|
-
require_relative "./
|
6
|
+
require_relative "./frame_bytes"
|
7
7
|
require_relative "./channel"
|
8
8
|
require_relative "./errors"
|
9
9
|
|
@@ -13,47 +13,32 @@ module AMQP
|
|
13
13
|
class Connection
|
14
14
|
# Establish a connection to an AMQP broker
|
15
15
|
# @param uri [String] URL on the format amqp://username:password@hostname/vhost, use amqps:// for encrypted connection
|
16
|
-
# @param read_loop_thread [Boolean]
|
16
|
+
# @param read_loop_thread [Boolean] If true run {#read_loop} in a background thread,
|
17
|
+
# otherwise the user have to run it explicitly, without {#read_loop} the connection won't function
|
17
18
|
# @option options [Boolean] connection_name (PROGRAM_NAME) Set a name for the connection to be able to identify
|
18
19
|
# the client from the broker
|
19
20
|
# @option options [Boolean] verify_peer (true) Verify broker's TLS certificate, set to false for self-signed certs
|
21
|
+
# @option options [Integer] connect_timeout (30) TCP connection timeout
|
20
22
|
# @option options [Integer] heartbeat (0) Heartbeat timeout, defaults to 0 and relies on TCP keepalive instead
|
21
23
|
# @option options [Integer] frame_max (131_072) Maximum frame size,
|
22
24
|
# the smallest of the client's and the broker's values will be used
|
23
25
|
# @option options [Integer] channel_max (2048) Maxium number of channels the client will be allowed to have open.
|
24
26
|
# Maxium allowed is 65_536. The smallest of the client's and the broker's value will be used.
|
27
|
+
# @option options [String] keepalive (60:10:3) TCP keepalive setting, 60s idle, 10s interval between probes, 3 probes
|
25
28
|
# @return [Connection]
|
26
|
-
def
|
29
|
+
def initialize(uri = "", read_loop_thread: true, **options)
|
27
30
|
uri = URI.parse(uri)
|
28
31
|
tls = uri.scheme == "amqps"
|
29
32
|
port = port_from_env || uri.port || (tls ? 5671 : 5672)
|
30
33
|
host = uri.host || "localhost"
|
31
34
|
user = uri.user || "guest"
|
32
35
|
password = uri.password || "guest"
|
33
|
-
vhost = URI.decode_www_form_component(uri.path[1
|
36
|
+
vhost = URI.decode_www_form_component(uri.path[1..] || "/")
|
34
37
|
options = URI.decode_www_form(uri.query || "").map! { |k, v| [k.to_sym, v] }.to_h.merge(options)
|
35
38
|
|
36
|
-
socket =
|
37
|
-
enable_tcp_keepalive(socket)
|
38
|
-
if tls
|
39
|
-
cert_store = OpenSSL::X509::Store.new
|
40
|
-
cert_store.set_default_paths
|
41
|
-
context = OpenSSL::SSL::SSLContext.new
|
42
|
-
context.cert_store = cert_store
|
43
|
-
context.verify_mode = OpenSSL::SSL::VERIFY_PEER unless [false, "false", "none"].include? options[:verify_peer]
|
44
|
-
socket = OpenSSL::SSL::SSLSocket.new(socket, context)
|
45
|
-
socket.sync_close = true # closing the TLS socket also closes the TCP socket
|
46
|
-
socket.hostname = host # SNI host
|
47
|
-
socket.connect
|
48
|
-
socket.post_connection_check(host) || raise(Error, "TLS certificate hostname doesn't match requested")
|
49
|
-
end
|
39
|
+
socket = open_socket(host, port, tls, options)
|
50
40
|
channel_max, frame_max, heartbeat = establish(socket, user, password, vhost, options)
|
51
|
-
Connection.new(socket, channel_max, frame_max, heartbeat, read_loop_thread: read_loop_thread)
|
52
|
-
end
|
53
41
|
|
54
|
-
# Requires an already established TCP/TLS socket
|
55
|
-
# @api private
|
56
|
-
def initialize(socket, channel_max, frame_max, heartbeat, read_loop_thread: true)
|
57
42
|
@socket = socket
|
58
43
|
@channel_max = channel_max.zero? ? 65_536 : channel_max
|
59
44
|
@frame_max = frame_max
|
@@ -66,6 +51,13 @@ module AMQP
|
|
66
51
|
Thread.new { read_loop } if read_loop_thread
|
67
52
|
end
|
68
53
|
|
54
|
+
# Alias for {#initialize}
|
55
|
+
# @see #initialize
|
56
|
+
# @deprecated
|
57
|
+
def self.connect(uri, read_loop_thread: true, **options)
|
58
|
+
new(uri, read_loop_thread: read_loop_thread, **options)
|
59
|
+
end
|
60
|
+
|
69
61
|
# The max frame size negotiated between the client and the broker
|
70
62
|
# @return [Integer]
|
71
63
|
attr_reader :frame_max
|
@@ -142,9 +134,13 @@ module AMQP
|
|
142
134
|
warn "AMQP-Client blocked by broker: #{blocked}" if blocked
|
143
135
|
@write_lock.synchronize do
|
144
136
|
warn "AMQP-Client unblocked by broker" if blocked
|
145
|
-
|
137
|
+
if RUBY_ENGINE == "truffleruby"
|
138
|
+
bytes.each { |b| @socket.write b }
|
139
|
+
else
|
140
|
+
@socket.write(*bytes)
|
141
|
+
end
|
146
142
|
end
|
147
|
-
rescue
|
143
|
+
rescue *READ_EXCEPTIONS => e
|
148
144
|
raise Error::ConnectionClosed.new(*@closed) if @closed
|
149
145
|
|
150
146
|
raise Error, "Could not write to socket, #{e.message}"
|
@@ -161,12 +157,12 @@ module AMQP
|
|
161
157
|
frame_start = String.new(capacity: 7)
|
162
158
|
frame_buffer = String.new(capacity: frame_max)
|
163
159
|
loop do
|
164
|
-
socket.read(7, frame_start)
|
160
|
+
socket.read(7, frame_start) || raise(IOError)
|
165
161
|
type, channel_id, frame_size = frame_start.unpack("C S> L>")
|
166
162
|
frame_max >= frame_size || raise(Error, "Frame size #{frame_size} larger than negotiated max frame size #{frame_max}")
|
167
163
|
|
168
164
|
# read the frame content
|
169
|
-
socket.read(frame_size, frame_buffer)
|
165
|
+
socket.read(frame_size, frame_buffer) || raise(IOError)
|
170
166
|
|
171
167
|
# make sure that the frame end is correct
|
172
168
|
frame_end = socket.readchar.ord
|
@@ -176,21 +172,26 @@ module AMQP
|
|
176
172
|
parse_frame(type, channel_id, frame_buffer) || return
|
177
173
|
end
|
178
174
|
nil
|
179
|
-
rescue
|
175
|
+
rescue *READ_EXCEPTIONS => e
|
180
176
|
@closed ||= [400, "read error: #{e.message}"]
|
181
177
|
nil # ignore read errors
|
182
178
|
ensure
|
183
179
|
@closed ||= [400, "unknown"]
|
184
180
|
@replies.close
|
185
181
|
begin
|
186
|
-
@
|
187
|
-
|
182
|
+
@write_lock.synchronize do
|
183
|
+
@socket.close
|
184
|
+
end
|
185
|
+
rescue *READ_EXCEPTIONS
|
188
186
|
nil
|
189
187
|
end
|
190
188
|
end
|
191
189
|
|
192
190
|
private
|
193
191
|
|
192
|
+
READ_EXCEPTIONS = [IOError, OpenSSL::OpenSSLError, SystemCallError,
|
193
|
+
RUBY_ENGINE == "jruby" ? java.lang.NullPointerException : nil].compact.freeze
|
194
|
+
|
194
195
|
def parse_frame(type, channel_id, buf)
|
195
196
|
case type
|
196
197
|
when 1 # method frame
|
@@ -216,7 +217,7 @@ module AMQP
|
|
216
217
|
@replies.push [:close_ok]
|
217
218
|
return false
|
218
219
|
when 60 # connection#blocked
|
219
|
-
reason_len = buf.
|
220
|
+
reason_len = buf.getbyte(4)
|
220
221
|
reason = buf.byteslice(5, reason_len).force_encoding("utf-8")
|
221
222
|
@blocked = reason
|
222
223
|
@write_lock.lock
|
@@ -256,7 +257,7 @@ module AMQP
|
|
256
257
|
when 50 # queue
|
257
258
|
case method_id
|
258
259
|
when 11 # declare-ok
|
259
|
-
queue_name_len = buf.
|
260
|
+
queue_name_len = buf.getbyte(4)
|
260
261
|
queue_name = buf.byteslice(5, queue_name_len).force_encoding("utf-8")
|
261
262
|
message_count, consumer_count = buf.byteslice(5 + queue_name_len, 8).unpack("L> L>")
|
262
263
|
@channels[channel_id].reply [:queue_declare_ok, queue_name, message_count, consumer_count]
|
@@ -276,17 +277,17 @@ module AMQP
|
|
276
277
|
when 11 # qos-ok
|
277
278
|
@channels[channel_id].reply [:basic_qos_ok]
|
278
279
|
when 21 # consume-ok
|
279
|
-
tag_len = buf.
|
280
|
+
tag_len = buf.getbyte(4)
|
280
281
|
tag = buf.byteslice(5, tag_len).force_encoding("utf-8")
|
281
282
|
@channels[channel_id].reply [:basic_consume_ok, tag]
|
282
283
|
when 30 # cancel
|
283
|
-
tag_len = buf.
|
284
|
+
tag_len = buf.getbyte(4)
|
284
285
|
tag = buf.byteslice(5, tag_len).force_encoding("utf-8")
|
285
|
-
no_wait = buf
|
286
|
+
no_wait = buf.getbyte(5 + tag_len) == 1
|
286
287
|
@channels[channel_id].close_consumer(tag)
|
287
288
|
write_bytes FrameBytes.basic_cancel_ok(@id, tag) unless no_wait
|
288
289
|
when 31 # cancel-ok
|
289
|
-
tag_len = buf.
|
290
|
+
tag_len = buf.getbyte(4)
|
290
291
|
tag = buf.byteslice(5, tag_len).force_encoding("utf-8")
|
291
292
|
@channels[channel_id].reply [:basic_cancel_ok, tag]
|
292
293
|
when 50 # return
|
@@ -294,23 +295,23 @@ module AMQP
|
|
294
295
|
pos = 7
|
295
296
|
reply_text = buf.byteslice(pos, reply_text_len).force_encoding("utf-8")
|
296
297
|
pos += reply_text_len
|
297
|
-
exchange_len = buf
|
298
|
+
exchange_len = buf.getbyte(pos)
|
298
299
|
pos += 1
|
299
300
|
exchange = buf.byteslice(pos, exchange_len).force_encoding("utf-8")
|
300
301
|
pos += exchange_len
|
301
|
-
routing_key_len = buf
|
302
|
+
routing_key_len = buf.getbyte(pos)
|
302
303
|
pos += 1
|
303
304
|
routing_key = buf.byteslice(pos, routing_key_len).force_encoding("utf-8")
|
304
305
|
@channels[channel_id].message_returned(reply_code, reply_text, exchange, routing_key)
|
305
306
|
when 60 # deliver
|
306
|
-
ctag_len = buf
|
307
|
+
ctag_len = buf.getbyte(4)
|
307
308
|
consumer_tag = buf.byteslice(5, ctag_len).force_encoding("utf-8")
|
308
309
|
pos = 5 + ctag_len
|
309
310
|
delivery_tag, redelivered, exchange_len = buf.byteslice(pos, 10).unpack("Q> C C")
|
310
311
|
pos += 8 + 1 + 1
|
311
312
|
exchange = buf.byteslice(pos, exchange_len).force_encoding("utf-8")
|
312
313
|
pos += exchange_len
|
313
|
-
rk_len = buf
|
314
|
+
rk_len = buf.getbyte(pos)
|
314
315
|
pos += 1
|
315
316
|
routing_key = buf.byteslice(pos, rk_len).force_encoding("utf-8")
|
316
317
|
@channels[channel_id].message_delivered(consumer_tag, delivery_tag, redelivered == 1, exchange, routing_key)
|
@@ -319,11 +320,11 @@ module AMQP
|
|
319
320
|
pos = 14
|
320
321
|
exchange = buf.byteslice(pos, exchange_len).force_encoding("utf-8")
|
321
322
|
pos += exchange_len
|
322
|
-
routing_key_len = buf
|
323
|
+
routing_key_len = buf.getbyte(pos)
|
323
324
|
pos += 1
|
324
325
|
routing_key = buf.byteslice(pos, routing_key_len).force_encoding("utf-8")
|
325
|
-
pos += routing_key_len
|
326
|
-
|
326
|
+
# pos += routing_key_len
|
327
|
+
# message_count = buf.byteslice(pos, 4).unpack1("L>")
|
327
328
|
@channels[channel_id].message_delivered(nil, delivery_tag, redelivered == 1, exchange, routing_key)
|
328
329
|
when 72 # get-empty
|
329
330
|
@channels[channel_id].basic_get_empty
|
@@ -357,7 +358,7 @@ module AMQP
|
|
357
358
|
end
|
358
359
|
when 2 # header
|
359
360
|
body_size = buf.unpack1("@4 Q>")
|
360
|
-
properties = Properties.decode(buf
|
361
|
+
properties = Properties.decode(buf, 12)
|
361
362
|
@channels[channel_id].header_delivered body_size, properties
|
362
363
|
when 3 # body
|
363
364
|
@channels[channel_id].body_delivered buf
|
@@ -377,21 +378,47 @@ module AMQP
|
|
377
378
|
args
|
378
379
|
end
|
379
380
|
|
381
|
+
# Connect to the host/port, optionally establish a TLS connection
|
382
|
+
# @return [Socket]
|
383
|
+
# @return [OpenSSL::SSL::SSLSocket]
|
384
|
+
def open_socket(host, port, tls, options)
|
385
|
+
connect_timeout = options.fetch(:connect_timeout, 30).to_i
|
386
|
+
socket = Socket.tcp host, port, connect_timeout: connect_timeout
|
387
|
+
keepalive = options.fetch(:keepalive, "").split(":", 3).map!(&:to_i)
|
388
|
+
enable_tcp_keepalive(socket, *keepalive)
|
389
|
+
if tls
|
390
|
+
cert_store = OpenSSL::X509::Store.new
|
391
|
+
cert_store.set_default_paths
|
392
|
+
context = OpenSSL::SSL::SSLContext.new
|
393
|
+
context.cert_store = cert_store
|
394
|
+
verify_peer = [false, "false", "none"].include? options[:verify_peer]
|
395
|
+
context.verify_mode = OpenSSL::SSL::VERIFY_PEER unless verify_peer
|
396
|
+
socket = OpenSSL::SSL::SSLSocket.new(socket, context)
|
397
|
+
socket.sync_close = true # closing the TLS socket also closes the TCP socket
|
398
|
+
socket.hostname = host # SNI host
|
399
|
+
socket.connect
|
400
|
+
socket.post_connection_check(host) || raise(Error, "TLS certificate hostname doesn't match requested")
|
401
|
+
end
|
402
|
+
socket
|
403
|
+
rescue SystemCallError, OpenSSL::OpenSSLError => e
|
404
|
+
raise Error, "Could not open a socket: #{e.message}"
|
405
|
+
end
|
406
|
+
|
380
407
|
# Negotiate a connection
|
381
408
|
# @return [Array<Integer, Integer, Integer>] channel_max, frame_max, heartbeat
|
382
|
-
def
|
409
|
+
def establish(socket, user, password, vhost, options)
|
383
410
|
channel_max, frame_max, heartbeat = nil
|
384
411
|
socket.write "AMQP\x00\x00\x09\x01"
|
385
412
|
buf = String.new(capacity: 4096)
|
386
413
|
loop do
|
387
414
|
begin
|
388
415
|
socket.readpartial(4096, buf)
|
389
|
-
rescue
|
416
|
+
rescue *READ_EXCEPTIONS => e
|
390
417
|
raise Error, "Could not establish AMQP connection: #{e.message}"
|
391
418
|
end
|
392
419
|
|
393
420
|
type, channel_id, frame_size = buf.unpack("C S> L>")
|
394
|
-
frame_end = buf
|
421
|
+
frame_end = buf.getbyte(frame_size + 7)
|
395
422
|
raise UnexpectedFrameEndError, frame_end if frame_end != 206
|
396
423
|
|
397
424
|
case type
|
@@ -428,32 +455,42 @@ module AMQP
|
|
428
455
|
else raise Error, "Unexpected frame type: #{type}"
|
429
456
|
end
|
430
457
|
end
|
431
|
-
rescue
|
458
|
+
rescue Exception => e
|
432
459
|
begin
|
433
460
|
socket.close
|
434
|
-
rescue
|
461
|
+
rescue *READ_EXCEPTIONS
|
435
462
|
nil
|
436
463
|
end
|
437
464
|
raise e
|
438
465
|
end
|
439
466
|
|
440
|
-
|
467
|
+
# Enable TCP keepalive, which is prefered to heartbeats
|
468
|
+
# @return [void]
|
469
|
+
def enable_tcp_keepalive(socket, idle = 60, interval = 10, count = 3)
|
441
470
|
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
442
|
-
|
443
|
-
|
444
|
-
|
471
|
+
if Socket.const_defined?(:TCP_KEEPIDLE) # linux/bsd
|
472
|
+
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPIDLE, idle)
|
473
|
+
elsif RUBY_PLATFORM.include? "darwin" # os x
|
474
|
+
# https://www.quickhack.net/nom/blog/2018-01-19-enable-tcp-keepalive-of-macos-and-linux-in-ruby.html
|
475
|
+
socket.setsockopt(Socket::IPPROTO_TCP, 0x10, idle)
|
476
|
+
else # windows
|
477
|
+
return
|
478
|
+
end
|
479
|
+
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPINTVL, interval)
|
480
|
+
socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_KEEPCNT, count)
|
445
481
|
rescue StandardError => e
|
446
482
|
warn "AMQP-Client could not enable TCP keepalive on socket. #{e.inspect}"
|
447
483
|
end
|
448
484
|
|
449
|
-
|
485
|
+
# Fetch the AMQP port number from ENV
|
486
|
+
# @return [Integer] A port number
|
487
|
+
# @return [nil] When the environment variable AMQP_PORT isn't set
|
488
|
+
def port_from_env
|
450
489
|
return unless (port = ENV["AMQP_PORT"])
|
451
490
|
|
452
491
|
port.to_i
|
453
492
|
end
|
454
493
|
|
455
|
-
private_class_method :establish, :enable_tcp_keepalive, :port_from_env
|
456
|
-
|
457
494
|
CLIENT_PROPERTIES = {
|
458
495
|
capabilities: {
|
459
496
|
authentication_failure_close: true,
|
@@ -10,9 +10,7 @@ module AMQP
|
|
10
10
|
# Having a class for each frame type is more expensive in terms of CPU and memory
|
11
11
|
# @api private
|
12
12
|
module FrameBytes
|
13
|
-
|
14
|
-
|
15
|
-
def connection_start_ok(response, properties)
|
13
|
+
def self.connection_start_ok(response, properties)
|
16
14
|
prop_tbl = Table.encode(properties)
|
17
15
|
[
|
18
16
|
1, # type: method
|
@@ -28,7 +26,7 @@ module AMQP
|
|
28
26
|
].pack("C S> L> S> S> L>a* Ca* L>a* Ca* C")
|
29
27
|
end
|
30
28
|
|
31
|
-
def connection_tune_ok(channel_max, frame_max, heartbeat)
|
29
|
+
def self.connection_tune_ok(channel_max, frame_max, heartbeat)
|
32
30
|
[
|
33
31
|
1, # type: method
|
34
32
|
0, # channel id
|
@@ -42,7 +40,7 @@ module AMQP
|
|
42
40
|
].pack("CS>L>S>S>S>L>S>C")
|
43
41
|
end
|
44
42
|
|
45
|
-
def connection_open(vhost)
|
43
|
+
def self.connection_open(vhost)
|
46
44
|
[
|
47
45
|
1, # type: method
|
48
46
|
0, # channel id
|
@@ -56,7 +54,7 @@ module AMQP
|
|
56
54
|
].pack("C S> L> S> S> Ca* CCC")
|
57
55
|
end
|
58
56
|
|
59
|
-
def connection_close(code, reason)
|
57
|
+
def self.connection_close(code, reason)
|
60
58
|
frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
|
61
59
|
[
|
62
60
|
1, # type: method
|
@@ -72,7 +70,7 @@ module AMQP
|
|
72
70
|
].pack("C S> L> S> S> S> Ca* S> S> C")
|
73
71
|
end
|
74
72
|
|
75
|
-
def connection_close_ok
|
73
|
+
def self.connection_close_ok
|
76
74
|
[
|
77
75
|
1, # type: method
|
78
76
|
0, # channel id
|
@@ -83,7 +81,7 @@ module AMQP
|
|
83
81
|
].pack("C S> L> S> S> C")
|
84
82
|
end
|
85
83
|
|
86
|
-
def channel_open(id)
|
84
|
+
def self.channel_open(id)
|
87
85
|
[
|
88
86
|
1, # type: method
|
89
87
|
id, # channel id
|
@@ -95,7 +93,7 @@ module AMQP
|
|
95
93
|
].pack("C S> L> S> S> C C")
|
96
94
|
end
|
97
95
|
|
98
|
-
def channel_close(id, reason, code)
|
96
|
+
def self.channel_close(id, reason, code)
|
99
97
|
frame_size = 2 + 2 + 2 + 1 + reason.bytesize + 2 + 2
|
100
98
|
[
|
101
99
|
1, # type: method
|
@@ -111,7 +109,7 @@ module AMQP
|
|
111
109
|
].pack("C S> L> S> S> S> Ca* S> S> C")
|
112
110
|
end
|
113
111
|
|
114
|
-
def channel_close_ok(id)
|
112
|
+
def self.channel_close_ok(id)
|
115
113
|
[
|
116
114
|
1, # type: method
|
117
115
|
id, # channel id
|
@@ -122,7 +120,7 @@ module AMQP
|
|
122
120
|
].pack("C S> L> S> S> C")
|
123
121
|
end
|
124
122
|
|
125
|
-
def exchange_declare(id, name, type, passive, durable, auto_delete, internal, arguments)
|
123
|
+
def self.exchange_declare(id, name, type, passive, durable, auto_delete, internal, arguments)
|
126
124
|
no_wait = false
|
127
125
|
bits = 0
|
128
126
|
bits |= (1 << 0) if passive
|
@@ -147,7 +145,7 @@ module AMQP
|
|
147
145
|
].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
|
148
146
|
end
|
149
147
|
|
150
|
-
def exchange_delete(id, name, if_unused, no_wait)
|
148
|
+
def self.exchange_delete(id, name, if_unused, no_wait)
|
151
149
|
bits = 0
|
152
150
|
bits |= (1 << 0) if if_unused
|
153
151
|
bits |= (1 << 1) if no_wait
|
@@ -165,7 +163,7 @@ module AMQP
|
|
165
163
|
].pack("C S> L> S> S> S> Ca* C C")
|
166
164
|
end
|
167
165
|
|
168
|
-
def exchange_bind(id, destination, source, binding_key, no_wait, arguments)
|
166
|
+
def self.exchange_bind(id, destination, source, binding_key, no_wait, arguments)
|
169
167
|
tbl = Table.encode(arguments)
|
170
168
|
frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
|
171
169
|
binding_key.bytesize + 1 + 4 + tbl.bytesize
|
@@ -185,7 +183,7 @@ module AMQP
|
|
185
183
|
].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
|
186
184
|
end
|
187
185
|
|
188
|
-
def exchange_unbind(id, destination, source, binding_key, no_wait, arguments)
|
186
|
+
def self.exchange_unbind(id, destination, source, binding_key, no_wait, arguments)
|
189
187
|
tbl = Table.encode(arguments)
|
190
188
|
frame_size = 2 + 2 + 2 + 1 + destination.bytesize + 1 + source.bytesize + 1 +
|
191
189
|
binding_key.bytesize + 1 + 4 + tbl.bytesize
|
@@ -205,7 +203,7 @@ module AMQP
|
|
205
203
|
].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
|
206
204
|
end
|
207
205
|
|
208
|
-
def queue_declare(id, name, passive, durable, exclusive, auto_delete, arguments)
|
206
|
+
def self.queue_declare(id, name, passive, durable, exclusive, auto_delete, arguments)
|
209
207
|
no_wait = false
|
210
208
|
bits = 0
|
211
209
|
bits |= (1 << 0) if passive
|
@@ -229,7 +227,7 @@ module AMQP
|
|
229
227
|
].pack("C S> L> S> S> S> Ca* C L>a* C")
|
230
228
|
end
|
231
229
|
|
232
|
-
def queue_delete(id, name, if_unused, if_empty, no_wait)
|
230
|
+
def self.queue_delete(id, name, if_unused, if_empty, no_wait)
|
233
231
|
bits = 0
|
234
232
|
bits |= (1 << 0) if if_unused
|
235
233
|
bits |= (1 << 1) if if_empty
|
@@ -248,7 +246,7 @@ module AMQP
|
|
248
246
|
].pack("C S> L> S> S> S> Ca* C C")
|
249
247
|
end
|
250
248
|
|
251
|
-
def queue_bind(id, queue, exchange, binding_key, no_wait, arguments)
|
249
|
+
def self.queue_bind(id, queue, exchange, binding_key, no_wait, arguments)
|
252
250
|
tbl = Table.encode(arguments)
|
253
251
|
frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 +
|
254
252
|
binding_key.bytesize + 1 + 4 + tbl.bytesize
|
@@ -268,7 +266,7 @@ module AMQP
|
|
268
266
|
].pack("C S> L> S> S> S> Ca* Ca* Ca* C L>a* C")
|
269
267
|
end
|
270
268
|
|
271
|
-
def queue_unbind(id, queue, exchange, binding_key, arguments)
|
269
|
+
def self.queue_unbind(id, queue, exchange, binding_key, arguments)
|
272
270
|
tbl = Table.encode(arguments)
|
273
271
|
frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1 + exchange.bytesize + 1 +
|
274
272
|
binding_key.bytesize + 4 + tbl.bytesize
|
@@ -287,7 +285,7 @@ module AMQP
|
|
287
285
|
].pack("C S> L> S> S> S> Ca* Ca* Ca* L>a* C")
|
288
286
|
end
|
289
287
|
|
290
|
-
def queue_purge(id, queue, no_wait)
|
288
|
+
def self.queue_purge(id, queue, no_wait)
|
291
289
|
frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
|
292
290
|
[
|
293
291
|
1, # type: method
|
@@ -302,7 +300,7 @@ module AMQP
|
|
302
300
|
].pack("C S> L> S> S> S> Ca* C C")
|
303
301
|
end
|
304
302
|
|
305
|
-
def basic_get(id, queue, no_ack)
|
303
|
+
def self.basic_get(id, queue, no_ack)
|
306
304
|
frame_size = 2 + 2 + 2 + 1 + queue.bytesize + 1
|
307
305
|
[
|
308
306
|
1, # type: method
|
@@ -317,7 +315,7 @@ module AMQP
|
|
317
315
|
].pack("C S> L> S> S> S> Ca* C C")
|
318
316
|
end
|
319
317
|
|
320
|
-
def basic_publish(id, exchange, routing_key, mandatory)
|
318
|
+
def self.basic_publish(id, exchange, routing_key, mandatory)
|
321
319
|
frame_size = 2 + 2 + 2 + 1 + exchange.bytesize + 1 + routing_key.bytesize + 1
|
322
320
|
[
|
323
321
|
1, # type: method
|
@@ -333,8 +331,8 @@ module AMQP
|
|
333
331
|
].pack("C S> L> S> S> S> Ca* Ca* C C")
|
334
332
|
end
|
335
333
|
|
336
|
-
def header(id, body_size, properties)
|
337
|
-
props = Properties.
|
334
|
+
def self.header(id, body_size, properties)
|
335
|
+
props = Properties.encode(properties)
|
338
336
|
frame_size = 2 + 2 + 8 + props.bytesize
|
339
337
|
[
|
340
338
|
2, # type: header
|
@@ -348,7 +346,7 @@ module AMQP
|
|
348
346
|
].pack("C S> L> S> S> Q> a* C")
|
349
347
|
end
|
350
348
|
|
351
|
-
def body(id, body_part)
|
349
|
+
def self.body(id, body_part)
|
352
350
|
[
|
353
351
|
3, # type: body
|
354
352
|
id, # channel id
|
@@ -358,7 +356,7 @@ module AMQP
|
|
358
356
|
].pack("C S> L> a* C")
|
359
357
|
end
|
360
358
|
|
361
|
-
def basic_consume(id, queue, tag, no_ack, exclusive, arguments)
|
359
|
+
def self.basic_consume(id, queue, tag, no_ack, exclusive, arguments)
|
362
360
|
no_local = false
|
363
361
|
no_wait = false
|
364
362
|
bits = 0
|
@@ -383,7 +381,7 @@ module AMQP
|
|
383
381
|
].pack("C S> L> S> S> S> Ca* Ca* C L>a* C")
|
384
382
|
end
|
385
383
|
|
386
|
-
def basic_cancel(id, consumer_tag, no_wait: false)
|
384
|
+
def self.basic_cancel(id, consumer_tag, no_wait: false)
|
387
385
|
frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
|
388
386
|
[
|
389
387
|
1, # type: method
|
@@ -397,7 +395,7 @@ module AMQP
|
|
397
395
|
].pack("C S> L> S> S> Ca* C C")
|
398
396
|
end
|
399
397
|
|
400
|
-
def basic_cancel_ok(id, consumer_tag)
|
398
|
+
def self.basic_cancel_ok(id, consumer_tag)
|
401
399
|
frame_size = 2 + 2 + 1 + consumer_tag.bytesize + 1
|
402
400
|
[
|
403
401
|
1, # type: method
|
@@ -410,7 +408,7 @@ module AMQP
|
|
410
408
|
].pack("C S> L> S> S> Ca* C")
|
411
409
|
end
|
412
410
|
|
413
|
-
def basic_ack(id, delivery_tag, multiple)
|
411
|
+
def self.basic_ack(id, delivery_tag, multiple)
|
414
412
|
frame_size = 2 + 2 + 8 + 1
|
415
413
|
[
|
416
414
|
1, # type: method
|
@@ -424,7 +422,7 @@ module AMQP
|
|
424
422
|
].pack("C S> L> S> S> Q> C C")
|
425
423
|
end
|
426
424
|
|
427
|
-
def basic_nack(id, delivery_tag, multiple, requeue)
|
425
|
+
def self.basic_nack(id, delivery_tag, multiple, requeue)
|
428
426
|
bits = 0
|
429
427
|
bits |= (1 << 0) if multiple
|
430
428
|
bits |= (1 << 1) if requeue
|
@@ -441,7 +439,7 @@ module AMQP
|
|
441
439
|
].pack("C S> L> S> S> Q> C C")
|
442
440
|
end
|
443
441
|
|
444
|
-
def basic_reject(id, delivery_tag, requeue)
|
442
|
+
def self.basic_reject(id, delivery_tag, requeue)
|
445
443
|
frame_size = 2 + 2 + 8 + 1
|
446
444
|
[
|
447
445
|
1, # type: method
|
@@ -455,7 +453,7 @@ module AMQP
|
|
455
453
|
].pack("C S> L> S> S> Q> C C")
|
456
454
|
end
|
457
455
|
|
458
|
-
def basic_qos(id, prefetch_size, prefetch_count, global)
|
456
|
+
def self.basic_qos(id, prefetch_size, prefetch_count, global)
|
459
457
|
frame_size = 2 + 2 + 4 + 2 + 1
|
460
458
|
[
|
461
459
|
1, # type: method
|
@@ -470,7 +468,7 @@ module AMQP
|
|
470
468
|
].pack("C S> L> S> S> L> S> C C")
|
471
469
|
end
|
472
470
|
|
473
|
-
def basic_recover(id, requeue)
|
471
|
+
def self.basic_recover(id, requeue)
|
474
472
|
frame_size = 2 + 2 + 1
|
475
473
|
[
|
476
474
|
1, # type: method
|
@@ -483,7 +481,7 @@ module AMQP
|
|
483
481
|
].pack("C S> L> S> S> C C")
|
484
482
|
end
|
485
483
|
|
486
|
-
def confirm_select(id, no_wait)
|
484
|
+
def self.confirm_select(id, no_wait)
|
487
485
|
[
|
488
486
|
1, # type: method
|
489
487
|
id, # channel id
|
@@ -495,7 +493,7 @@ module AMQP
|
|
495
493
|
].pack("C S> L> S> S> C C")
|
496
494
|
end
|
497
495
|
|
498
|
-
def tx_select(id)
|
496
|
+
def self.tx_select(id)
|
499
497
|
frame_size = 2 + 2
|
500
498
|
[
|
501
499
|
1, # type: method
|
@@ -507,7 +505,7 @@ module AMQP
|
|
507
505
|
].pack("C S> L> S> S> C")
|
508
506
|
end
|
509
507
|
|
510
|
-
def tx_commit(id)
|
508
|
+
def self.tx_commit(id)
|
511
509
|
frame_size = 2 + 2
|
512
510
|
[
|
513
511
|
1, # type: method
|
@@ -519,7 +517,7 @@ module AMQP
|
|
519
517
|
].pack("C S> L> S> S> C")
|
520
518
|
end
|
521
519
|
|
522
|
-
def tx_rollback(id)
|
520
|
+
def self.tx_rollback(id)
|
523
521
|
frame_size = 2 + 2
|
524
522
|
[
|
525
523
|
1, # type: method
|