amqp-client 1.0.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|