rabbitmq 0.0.1 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 244f595aa2d3971af7abf7ca4cc7ef6c56c210c1
4
- data.tar.gz: 3d416e1b3667a19c547bc11a81ca0cdf6c2530ed
3
+ metadata.gz: 1c1c764cdfb743927b47bbd5165898582458c656
4
+ data.tar.gz: dda4411b342ca6e609562976f6fc981d9eb67577
5
5
  SHA512:
6
- metadata.gz: 9440df7f81db2e10d88d69816da91a1f059db6581c5d7e136b58bee98b5e516e4f8250ad87f7bbb43ff53b790915da1d44566b05998f33036b06b9e8742d9e3a
7
- data.tar.gz: 48489bb898751dd7a433e5a7456216a08650736b6b84b9fcc67acd21eef003da45d4d60f767626458d92569394c8e9c5cc7b446f378a7a1a3c00a3d033ec3b9f
6
+ metadata.gz: 6d3cee85a69364b25a15087b264fb47c906bbd1dd94c76a9fb56ffb06171f093ef9ffa78363dabb0dca23c2def71bf2bbe45c2d4a9e0b029e92074beb6dd4c9e
7
+ data.tar.gz: 5d418e13636abdd2189c7b49072abdf2ca4a9ed053dc7711d2fc60d009067a8a3202ecb77548d3c77df671d84ce49c8d1991d8110e10352ad2813c5dd4b85da3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Joe McIlvain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+
2
+ require 'rake/clean'
3
+
4
+ FILES = {}
5
+
6
+ task :default => :build
7
+
8
+ def self.file_task(filename, opts, &block)
9
+ name, dep = opts.is_a?(Hash) ? opts.to_a.first : [opts, nil]
10
+
11
+ FILES[name] = filename
12
+ CLEAN.include filename
13
+ task name => filename
14
+
15
+ if dep
16
+ file filename => FILES[dep], &block
17
+ else
18
+ file filename, &block
19
+ end
20
+ end
21
+
22
+ file_task 'rabbitmq-c.tar.gz', :download_tarball do
23
+ version = "0.6.0"
24
+ release = "https://github.com/alanxz/rabbitmq-c/releases/download/v#{version}/rabbitmq-c-#{version}.tar.gz"
25
+ system "wget #{release}"
26
+ system "mv #{File.basename(release)} #{FILES[:download_tarball]}"
27
+ end
28
+
29
+ file_task 'rabbitmq-c', :download => :download_tarball do
30
+ system "tar -xf #{FILES[:download_tarball]}"
31
+ system "mv rabbitmq-c-* #{FILES[:download]}"
32
+ end
33
+
34
+ file_task 'config.status', :configure => :download do
35
+ system "bash -c 'cd #{FILES[:download]} && ./configure'"
36
+ system "cp #{FILES[:download]}/#{FILES[:configure]} ./"
37
+ end
38
+
39
+ file_task 'librabbitmq.so', :build => :configure do
40
+ system "bash -c 'cd #{FILES[:download]} && make'"
41
+ system "cp #{FILES[:download]}/librabbitmq/.libs/#{FILES[:build]} ."
42
+ end
data/lib/rabbitmq.rb CHANGED
@@ -1,2 +1,8 @@
1
1
 
2
2
  require_relative 'rabbitmq/ffi'
3
+ require_relative 'rabbitmq/ffi/ext'
4
+ require_relative 'rabbitmq/ffi/error'
5
+
6
+ require_relative 'rabbitmq/util'
7
+
8
+ require_relative 'rabbitmq/connection'
@@ -0,0 +1,112 @@
1
+
2
+ module RabbitMQ
3
+ class Connection
4
+ def initialize *args
5
+ @ptr = FFI.amqp_new_connection
6
+ parse_info(*args)
7
+ create_socket!
8
+
9
+ @finalizer = self.class.send :create_finalizer_for, @ptr
10
+ ObjectSpace.define_finalizer self, @finalizer
11
+ end
12
+
13
+ def destroy
14
+ if @finalizer
15
+ @finalizer.call
16
+ ObjectSpace.undefine_finalizer self
17
+ end
18
+ @ptr = @socket = @finalizer = nil
19
+ end
20
+
21
+ class DestroyedError < RuntimeError; end
22
+
23
+ # @private
24
+ def self.create_finalizer_for(ptr)
25
+ Proc.new do
26
+ FFI.amqp_connection_close(ptr, 200)
27
+ FFI.amqp_destroy_connection(ptr)
28
+ end
29
+ end
30
+
31
+ def user; @info[:user]; end
32
+ def password; @info[:password]; end
33
+ def host; @info[:host]; end
34
+ def vhost; @info[:vhost]; end
35
+ def port; @info[:port]; end
36
+ def ssl?; @info[:ssl]; end
37
+
38
+ def max_channels; @max_channels ||= 0; end; attr_writer :max_channels
39
+ def max_frame_size; @max_frame_size ||= 131072; end; attr_writer :max_frame_size
40
+ def heartbeat_interval; 0; end # not fully implemented in librabbitmq
41
+
42
+ def start
43
+ close # Close if already open
44
+ connect_socket!
45
+ login!
46
+ open_channel!
47
+ end
48
+
49
+ def close
50
+ raise DestroyedError unless @ptr
51
+ FFI.amqp_connection_close(@ptr, 200)
52
+ end
53
+
54
+ private def parse_info url=nil
55
+ info = FFI::ConnectionInfo.new
56
+
57
+ if url
58
+ url_ptr = Util.strdup_ptr(url)
59
+ Util.error_check :"parsing connection URL",
60
+ FFI.amqp_parse_url(url_ptr, info)
61
+
62
+ # We must copy ConnectionInfo before the url_ptr is freed.
63
+ @info = info.to_h
64
+ url_ptr.free
65
+ else
66
+ FFI.amqp_default_connection_info(info)
67
+ @info = info.to_h
68
+ end
69
+ end
70
+
71
+ private def create_socket!
72
+ raise DestroyedError unless @ptr
73
+
74
+ @socket = FFI.amqp_tcp_socket_new(@ptr)
75
+ Util.null_check :"creating a socket", @socket
76
+ end
77
+
78
+ private def connect_socket!
79
+ raise DestroyedError unless @ptr
80
+ raise NotImplementedError if ssl?
81
+
82
+ create_socket!
83
+ Util.error_check :"opening a socket",
84
+ FFI.amqp_socket_open(@socket, host, port)
85
+ end
86
+
87
+ private def login!
88
+ raise DestroyedError unless @ptr
89
+
90
+ rpc_check :"logging in",
91
+ FFI.amqp_login(@ptr, vhost, max_channels, max_frame_size,
92
+ heartbeat_interval, :plain, :string, user, :string, password)
93
+
94
+ @server_properties = FFI::Table.new(FFI.amqp_get_server_properties(@ptr)).to_h
95
+ end
96
+
97
+ private def open_channel!(number=1)
98
+ raise DestroyedError unless @ptr
99
+
100
+ FFI.amqp_channel_open(@ptr, number)
101
+ rpc_check :"opening channel", FFI.amqp_get_rpc_reply(@ptr)
102
+ end
103
+
104
+ private def rpc_check action, res
105
+ case res[:reply_type]
106
+ when :library_exception; Util.error_check action, res[:library_error]
107
+ when :server_exception; raise NotImplementedError
108
+ else res
109
+ end
110
+ end
111
+ end
112
+ end
data/lib/rabbitmq/ffi.rb CHANGED
@@ -6,24 +6,10 @@ module RabbitMQ
6
6
  module FFI
7
7
  extend ::FFI::Library
8
8
 
9
- def self.available?
10
- @available
11
- end
12
-
13
- begin
14
- lib_name = 'librabbitmq'
15
- lib_paths = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
16
- .map { |path| "#{path}/#{lib_name}.#{::FFI::Platform::LIBSUFFIX}" }
17
- ffi_lib lib_paths + [lib_name]
18
- @available = true
19
- rescue LoadError
20
- warn ""
21
- warn "WARNING: #{self} is not available without librabbitmq."
22
- warn ""
23
- @available = false
24
- end
9
+ ffi_lib \
10
+ File.expand_path("../../ext/rabbitmq/librabbitmq.so", File.dirname(__FILE__))
25
11
 
26
- if available?
12
+ begin # TODO: remove begin/end block
27
13
  opts = {
28
14
  blocking: true # only necessary on MRI to deal with the GIL.
29
15
  }
@@ -33,10 +19,87 @@ module RabbitMQ
33
19
  attach_function :amqp_version_number, [], :uint32, **opts
34
20
  attach_function :amqp_version, [], :string, **opts
35
21
 
36
- Boolean = :int
37
- MethodNumber = :uint32
38
- Flags = :uint32
39
- Channel = :uint16
22
+ class Timeval < ::FFI::Struct
23
+ layout :tv_sec, :time_t,
24
+ :tv_usec, :suseconds_t
25
+ end
26
+
27
+ class Boolean
28
+ extend ::FFI::DataConverter
29
+ native_type ::FFI::TypeDefs[:int]
30
+ def self.to_native val, ctx; val ? 1 : 0; end
31
+ def self.from_native val, ctx; val != 0; end
32
+ end
33
+
34
+ MethodNumber = enum ::FFI::TypeDefs[:uint32], [
35
+ :connection_start, 0x000A000A, # 10, 10; 655370
36
+ :connection_start_ok, 0x000A000B, # 10, 11; 655371
37
+ :connection_secure, 0x000A0014, # 10, 20; 655380
38
+ :connection_secure_ok, 0x000A0015, # 10, 21; 655381
39
+ :connection_tune, 0x000A001E, # 10, 30; 655390
40
+ :connection_tune_ok, 0x000A001F, # 10, 31; 655391
41
+ :connection_open, 0x000A0028, # 10, 40; 655400
42
+ :connection_open_ok, 0x000A0029, # 10, 41; 655401
43
+ :connection_close, 0x000A0032, # 10, 50; 655410
44
+ :connection_close_ok, 0x000A0033, # 10, 51; 655411
45
+ :connection_blocked, 0x000A003C, # 10, 60; 655420
46
+ :connection_unblocked, 0x000A003D, # 10, 61; 655421
47
+ :channel_open, 0x0014000A, # 20, 10; 1310730
48
+ :channel_open_ok, 0x0014000B, # 20, 11; 1310731
49
+ :channel_flow, 0x00140014, # 20, 20; 1310740
50
+ :channel_flow_ok, 0x00140015, # 20, 21; 1310741
51
+ :channel_close, 0x00140028, # 20, 40; 1310760
52
+ :channel_close_ok, 0x00140029, # 20, 41; 1310761
53
+ :access_request, 0x001E000A, # 30, 10; 1966090
54
+ :access_request_ok, 0x001E000B, # 30, 11; 1966091
55
+ :exchange_declare, 0x0028000A, # 40, 10; 2621450
56
+ :exchange_declare_ok, 0x0028000B, # 40, 11; 2621451
57
+ :exchange_delete, 0x00280014, # 40, 20; 2621460
58
+ :exchange_delete_ok, 0x00280015, # 40, 21; 2621461
59
+ :exchange_bind, 0x0028001E, # 40, 30; 2621470
60
+ :exchange_bind_ok, 0x0028001F, # 40, 31; 2621471
61
+ :exchange_unbind, 0x00280028, # 40, 40; 2621480
62
+ :exchange_unbind_ok, 0x00280033, # 40, 51; 2621491
63
+ :queue_declare, 0x0032000A, # 50, 10; 3276810
64
+ :queue_declare_ok, 0x0032000B, # 50, 11; 3276811
65
+ :queue_bind, 0x00320014, # 50, 20; 3276820
66
+ :queue_bind_ok, 0x00320015, # 50, 21; 3276821
67
+ :queue_purge, 0x0032001E, # 50, 30; 3276830
68
+ :queue_purge_ok, 0x0032001F, # 50, 31; 3276831
69
+ :queue_delete, 0x00320028, # 50, 40; 3276840
70
+ :queue_delete_ok, 0x00320029, # 50, 41; 3276841
71
+ :queue_unbind, 0x00320032, # 50, 50; 3276850
72
+ :queue_unbind_ok, 0x00320033, # 50, 51; 3276851
73
+ :basic_qos, 0x003C000A, # 60, 10; 3932170
74
+ :basic_qos_ok, 0x003C000B, # 60, 11; 3932171
75
+ :basic_consume, 0x003C0014, # 60, 20; 3932180
76
+ :basic_consume_ok, 0x003C0015, # 60, 21; 3932181
77
+ :basic_cancel, 0x003C001E, # 60, 30; 3932190
78
+ :basic_cancel_ok, 0x003C001F, # 60, 31; 3932191
79
+ :basic_publish, 0x003C0028, # 60, 40; 3932200
80
+ :basic_return, 0x003C0032, # 60, 50; 3932210
81
+ :basic_deliver, 0x003C003C, # 60, 60; 3932220
82
+ :basic_get, 0x003C0046, # 60, 70; 3932230
83
+ :basic_get_ok, 0x003C0047, # 60, 71; 3932231
84
+ :basic_get_empty, 0x003C0048, # 60, 72; 3932232
85
+ :basic_ack, 0x003C0050, # 60, 80; 3932240
86
+ :basic_reject, 0x003C005A, # 60, 90; 3932250
87
+ :basic_recover_async, 0x003C0064, # 60, 100; 3932260
88
+ :basic_recover, 0x003C006E, # 60, 110; 3932270
89
+ :basic_recover_ok, 0x003C006F, # 60, 111; 3932271
90
+ :basic_nack, 0x003C0078, # 60, 120; 3932280
91
+ :tx_select, 0x005A000A, # 90, 10; 5898250
92
+ :tx_select_ok, 0x005A000B, # 90, 11; 5898251
93
+ :tx_commit, 0x005A0014, # 90, 20; 5898260
94
+ :tx_commit_ok, 0x005A0015, # 90, 21; 5898261
95
+ :tx_rollback, 0x005A001E, # 90, 30; 5898270
96
+ :tx_rollback_ok, 0x005A001F, # 90, 31; 5898271
97
+ :confirm_select, 0x0055000A, # 85, 10; 5570570
98
+ :confirm_select_ok, 0x0055000B, # 85, 11; 5570571
99
+ ]
100
+
101
+ Flags = :uint32
102
+ Channel = :uint16
40
103
 
41
104
  class Bytes < ::FFI::Struct
42
105
  layout :len, :size_t,
@@ -58,6 +121,27 @@ module RabbitMQ
58
121
  :entries, :pointer
59
122
  end
60
123
 
124
+ FieldValueKind = enum ::FFI::TypeDefs[:uint8], [
125
+ :boolean, 't'.ord,
126
+ :i8, 'b'.ord,
127
+ :u8, 'B'.ord,
128
+ :i16, 's'.ord,
129
+ :u16, 'u'.ord,
130
+ :i32, 'I'.ord,
131
+ :u32, 'i'.ord,
132
+ :i64, 'l'.ord,
133
+ :u64, 'L'.ord,
134
+ :f32, 'f'.ord,
135
+ :f64, 'd'.ord,
136
+ :decimal, 'D'.ord,
137
+ :utf8, 'S'.ord,
138
+ :array, 'A'.ord,
139
+ :timestamp, 'T'.ord,
140
+ :table, 'F'.ord,
141
+ :void, 'V'.ord,
142
+ :bytes, 'x'.ord,
143
+ ]
144
+
61
145
  class FieldValueValue < ::FFI::Union
62
146
  layout :boolean, Boolean,
63
147
  :i8, :int8,
@@ -77,7 +161,7 @@ module RabbitMQ
77
161
  end
78
162
 
79
163
  class FieldValue < ::FFI::Struct
80
- layout :kind, :uint8,
164
+ layout :kind, FieldValueKind,
81
165
  :value, FieldValueValue
82
166
  end
83
167
 
@@ -86,27 +170,6 @@ module RabbitMQ
86
170
  :value, FieldValue
87
171
  end
88
172
 
89
- FieldValueKindEnum = enum [
90
- :boolean, 't'.ord,
91
- :i8, 'b'.ord,
92
- :u8, 'B'.ord,
93
- :i16, 's'.ord,
94
- :u16, 'u'.ord,
95
- :i32, 'I'.ord,
96
- :u32, 'i'.ord,
97
- :i64, 'l'.ord,
98
- :u64, 'L'.ord,
99
- :f32, 'f'.ord,
100
- :f64, 'd'.ord,
101
- :decimal, 'D'.ord,
102
- :utf8, 'S'.ord,
103
- :array, 'A'.ord,
104
- :timestamp, 'T'.ord,
105
- :table, 'F'.ord,
106
- :void, 'V'.ord,
107
- :bytes, 'x'.ord,
108
- ]
109
-
110
173
  class PoolBlocklist < ::FFI::Struct
111
174
  layout :num_blocks, :int,
112
175
  :blocklist, :pointer
@@ -153,7 +216,7 @@ module RabbitMQ
153
216
  :payload, FramePayload
154
217
  end
155
218
 
156
- ResponseTypeEnum = enum [
219
+ ResponseType = enum [
157
220
  :none, 0,
158
221
  :normal,
159
222
  :library_exception,
@@ -161,18 +224,18 @@ module RabbitMQ
161
224
  ]
162
225
 
163
226
  class RpcReply < ::FFI::Struct
164
- layout :reply_type, ResponseTypeEnum,
227
+ layout :reply_type, ResponseType,
165
228
  :reply, Method,
166
229
  :library_error, :int
167
230
  end
168
231
 
169
- SaslMethodEnum = enum [
232
+ SaslMethod = enum [
170
233
  :plain, 0,
171
234
  ]
172
235
 
173
236
  ConnectionState = :pointer
174
237
 
175
- StatusEnum = enum [
238
+ Status = enum [
176
239
  :ok, 0x0,
177
240
  :no_memory, -0x0001,
178
241
  :bad_amqp_data, -0x0002,
@@ -190,6 +253,8 @@ module RabbitMQ
190
253
  :timer_failure, -0x000E,
191
254
  :heartbeat_timeout, -0x000F,
192
255
  :unexpected_state, -0x0010,
256
+ :unexpected_socket_closed, -0x0011,
257
+ :unexpected_socket_inuse, -0x0012,
193
258
  :tcp_error, -0x0100,
194
259
  :tcp_socketlib_init_error, -0x0101,
195
260
  :ssl_error, -0x0200,
@@ -198,7 +263,7 @@ module RabbitMQ
198
263
  :ssl_connection_failed, -0x0203,
199
264
  ]
200
265
 
201
- DeliveryModeEnum = enum [
266
+ DeliveryMode = enum [
202
267
  :nonpersistent, 1,
203
268
  :persistent, 2,
204
269
  ]
@@ -208,10 +273,10 @@ module RabbitMQ
208
273
 
209
274
  attach_function :amqp_method_name, [MethodNumber], :string, **opts
210
275
  attach_function :amqp_method_has_content, [MethodNumber], Boolean, **opts
211
- attach_function :amqp_decode_method, [MethodNumber, :pointer, Bytes, :pointer], :int, **opts
212
- attach_function :amqp_decode_properties, [:uint16, :pointer, Bytes, :pointer], :int, **opts
213
- attach_function :amqp_encode_method, [MethodNumber, :pointer, Bytes], :int, **opts
214
- attach_function :amqp_encode_properties, [:uint16, :pointer, Bytes], :int, **opts
276
+ attach_function :amqp_decode_method, [MethodNumber, Pool.ptr, Bytes, :pointer], Status, **opts
277
+ attach_function :amqp_decode_properties, [:uint16, Pool.ptr, Bytes, :pointer], Status, **opts
278
+ attach_function :amqp_encode_method, [MethodNumber, :pointer, Bytes], Status, **opts
279
+ attach_function :amqp_encode_properties, [:uint16, :pointer, Bytes], Status, **opts
215
280
 
216
281
  class ConnectionStart < ::FFI::Struct
217
282
  layout :version_major, :uint8,
@@ -622,31 +687,31 @@ module RabbitMQ
622
687
  :cluster_id, Bytes
623
688
  end
624
689
 
625
- attach_function :amqp_channel_open, [ConnectionState, Channel], :pointer, **opts
626
- attach_function :amqp_channel_flow, [ConnectionState, Channel, Boolean], :pointer, **opts
627
- attach_function :amqp_exchange_declare, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Table], :pointer, **opts
628
- attach_function :amqp_exchange_delete, [ConnectionState, Channel, Bytes, Boolean], :pointer, **opts
629
- attach_function :amqp_exchange_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
630
- attach_function :amqp_exchange_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
631
- attach_function :amqp_queue_declare, [ConnectionState, Channel, Bytes, Boolean, Boolean, Boolean, Boolean, Table], :pointer, **opts
632
- attach_function :amqp_queue_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
633
- attach_function :amqp_queue_purge, [ConnectionState, Channel, Bytes], :pointer, **opts
634
- attach_function :amqp_queue_delete, [ConnectionState, Channel, Bytes, Boolean, Boolean], :pointer, **opts
635
- attach_function :amqp_queue_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], :pointer, **opts
636
- attach_function :amqp_basic_qos, [ConnectionState, Channel, :uint32, :uint16, Boolean], :pointer, **opts
637
- attach_function :amqp_basic_consume, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Boolean, Table], :pointer, **opts
638
- attach_function :amqp_basic_cancel, [ConnectionState, Channel, Bytes], :pointer, **opts
639
- attach_function :amqp_basic_recover, [ConnectionState, Channel, Boolean], :pointer, **opts
640
- attach_function :amqp_tx_select, [ConnectionState, Channel], :pointer, **opts
641
- attach_function :amqp_tx_commit, [ConnectionState, Channel], :pointer, **opts
642
- attach_function :amqp_tx_rollback, [ConnectionState, Channel], :pointer, **opts
643
- attach_function :amqp_confirm_select, [ConnectionState, Channel], :pointer, **opts
644
-
645
- attach_function :init_amqp_pool, [:pointer, :size_t], :void, **opts
646
- attach_function :recycle_amqp_pool, [:pointer], :void, **opts
647
- attach_function :empty_amqp_pool, [:pointer], :void, **opts
648
- attach_function :amqp_pool_alloc, [:pointer, :size_t], :pointer, **opts
649
- attach_function :amqp_pool_alloc_bytes, [:pointer, :size_t, :pointer], :void, **opts
690
+ attach_function :amqp_channel_open, [ConnectionState, Channel], ChannelOpenOk.ptr, **opts
691
+ attach_function :amqp_channel_flow, [ConnectionState, Channel, Boolean], ChannelFlowOk.ptr, **opts
692
+ attach_function :amqp_exchange_declare, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Table], ExchangeDeclareOk.ptr, **opts
693
+ attach_function :amqp_exchange_delete, [ConnectionState, Channel, Bytes, Boolean], ExchangeDeleteOk.ptr, **opts
694
+ attach_function :amqp_exchange_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], ExchangeBindOk.ptr, **opts
695
+ attach_function :amqp_exchange_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], ExchangeUnbindOk.ptr, **opts
696
+ attach_function :amqp_queue_declare, [ConnectionState, Channel, Bytes, Boolean, Boolean, Boolean, Boolean, Table], QueueDeclareOk.ptr, **opts
697
+ attach_function :amqp_queue_bind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], QueueBindOk.ptr, **opts
698
+ attach_function :amqp_queue_purge, [ConnectionState, Channel, Bytes], QueuePurgeOk.ptr, **opts
699
+ attach_function :amqp_queue_delete, [ConnectionState, Channel, Bytes, Boolean, Boolean], QueueDeleteOk.ptr, **opts
700
+ attach_function :amqp_queue_unbind, [ConnectionState, Channel, Bytes, Bytes, Bytes, Table], QueueUnbindOk.ptr, **opts
701
+ attach_function :amqp_basic_qos, [ConnectionState, Channel, :uint32, :uint16, Boolean], BasicQosOk.ptr, **opts
702
+ attach_function :amqp_basic_consume, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, Boolean, Table], BasicConsumeOk.ptr, **opts
703
+ attach_function :amqp_basic_cancel, [ConnectionState, Channel, Bytes], BasicCancelOk.ptr, **opts
704
+ attach_function :amqp_basic_recover, [ConnectionState, Channel, Boolean], BasicRecoverOk.ptr, **opts
705
+ attach_function :amqp_tx_select, [ConnectionState, Channel], TxSelect.ptr, **opts
706
+ attach_function :amqp_tx_commit, [ConnectionState, Channel], TxCommit.ptr, **opts
707
+ attach_function :amqp_tx_rollback, [ConnectionState, Channel], TxRollback.ptr, **opts
708
+ attach_function :amqp_confirm_select, [ConnectionState, Channel], ConfirmSelect.ptr, **opts
709
+
710
+ attach_function :init_amqp_pool, [Pool.ptr, :size_t], :void, **opts
711
+ attach_function :recycle_amqp_pool, [Pool.ptr], :void, **opts
712
+ attach_function :empty_amqp_pool, [Pool.ptr], :void, **opts
713
+ attach_function :amqp_pool_alloc, [Pool.ptr, :size_t], :pointer, **opts
714
+ attach_function :amqp_pool_alloc_bytes, [Pool.ptr, :size_t, Bytes.ptr], :void, **opts
650
715
 
651
716
  attach_function :amqp_cstring_bytes, [:string], Bytes, **opts
652
717
  attach_function :amqp_bytes_malloc_dup, [Bytes], Bytes, **opts
@@ -654,51 +719,55 @@ module RabbitMQ
654
719
  attach_function :amqp_bytes_free, [Bytes], :void, **opts
655
720
 
656
721
  attach_function :amqp_new_connection, [], ConnectionState, **opts
657
- attach_function :amqp_get_sockfd, [ConnectionState], :int, **opts
658
- attach_function :amqp_set_sockfd, [ConnectionState, :int], :void, **opts
659
- attach_function :amqp_tune_connection, [ConnectionState, :int, :int, :int], :int, **opts
660
- attach_function :amqp_get_channel_max, [ConnectionState], :int, **opts
661
- attach_function :amqp_destroy_connection, [ConnectionState], :int, **opts
662
-
663
- attach_function :amqp_handle_input, [ConnectionState, Bytes, :pointer], :int, **opts
664
- attach_function :amqp_release_buffers_ok, [ConnectionState], Boolean, **opts
665
- attach_function :amqp_release_buffers, [ConnectionState], :void, **opts
666
- attach_function :amqp_maybe_release_buffers, [ConnectionState], :void, **opts
667
- attach_function :amqp_maybe_release_buffers_on_channel, [ConnectionState, Channel], :void, **opts
668
- attach_function :amqp_send_frame, [ConnectionState, :pointer], :int, **opts
722
+ attach_function :amqp_get_sockfd, [ConnectionState], :int, **opts
723
+ attach_function :amqp_set_sockfd, [ConnectionState, :int], :void, **opts
724
+ attach_function :amqp_tune_connection, [ConnectionState, :int, :int, :int], Status, **opts
725
+ attach_function :amqp_get_channel_max, [ConnectionState], :int, **opts
726
+ attach_function :amqp_get_frame_max, [ConnectionState], :int, **opts
727
+ attach_function :amqp_get_heartbeat, [ConnectionState], :int, **opts
728
+ attach_function :amqp_destroy_connection, [ConnectionState], Status, **opts
729
+
730
+ attach_function :amqp_handle_input, [ConnectionState, Bytes, Frame.ptr], Status, **opts
731
+ attach_function :amqp_release_buffers_ok, [ConnectionState], Boolean, **opts
732
+ attach_function :amqp_release_buffers, [ConnectionState], :void, **opts
733
+ attach_function :amqp_maybe_release_buffers, [ConnectionState], :void, **opts
734
+ attach_function :amqp_maybe_release_buffers_on_channel, [ConnectionState, Channel], :void, **opts
735
+ attach_function :amqp_send_frame, [ConnectionState, Frame.ptr], Status, **opts
669
736
 
670
737
  attach_function :amqp_table_entry_cmp, [:pointer, :pointer], :int, **opts
671
- attach_function :amqp_open_socket, [:string, :int], :int, **opts
672
-
673
- attach_function :amqp_send_header, [ConnectionState], :int, **opts
674
- attach_function :amqp_frames_enqueued, [ConnectionState], Boolean, **opts
675
- attach_function :amqp_simple_wait_frame, [ConnectionState, :pointer], :int, **opts
676
- attach_function :amqp_simple_wait_frame_noblock, [ConnectionState, :pointer, :pointer], :int, **opts
677
- attach_function :amqp_simple_wait_method, [ConnectionState, Channel, MethodNumber, :pointer], :int, **opts
678
- attach_function :amqp_send_method, [ConnectionState, Channel, MethodNumber, :pointer], :int, **opts
679
-
680
- attach_function :amqp_simple_rpc, [ConnectionState, Channel, MethodNumber, :pointer, :pointer], RpcReply, **opts
681
- attach_function :amqp_simple_rpc_decoded, [ConnectionState, Channel, MethodNumber, MethodNumber, :pointer], :pointer, **opts
682
- attach_function :amqp_get_rpc_reply, [ConnectionState], RpcReply, **opts
683
- attach_function :amqp_login, [ConnectionState, :string, :int, :int, :int, SaslMethodEnum], RpcReply, **opts
684
- attach_function :amqp_login_with_properties, [ConnectionState, :string, :int, :int, :int, :pointer, SaslMethodEnum], RpcReply, **opts
685
- attach_function :amqp_channel_close, [ConnectionState, Channel, :int], RpcReply, **opts
686
- attach_function :amqp_connection_close, [ConnectionState, :int], RpcReply, **opts
687
-
688
- attach_function :amqp_basic_publish, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, :pointer, Bytes], :int, **opts
689
- attach_function :amqp_basic_ack, [ConnectionState, Channel, :uint64, Boolean], :int, **opts
690
- attach_function :amqp_basic_get, [ConnectionState, Channel, Bytes, Boolean], :int, **opts
691
- attach_function :amqp_basic_reject, [ConnectionState, Channel, :uint64, Boolean], :int, **opts
692
- attach_function :amqp_basic_nack, [ConnectionState, Channel, :uint64, Boolean, Boolean], :int, **opts
738
+
739
+ attach_function :amqp_open_socket, [:string, :int], Status, **opts
740
+
741
+ attach_function :amqp_send_header, [ConnectionState], Status, **opts
742
+ attach_function :amqp_frames_enqueued, [ConnectionState], Boolean, **opts
743
+ attach_function :amqp_simple_wait_frame, [ConnectionState, Frame.ptr], Status, **opts
744
+ attach_function :amqp_simple_wait_frame_noblock, [ConnectionState, Frame.ptr, Timeval.ptr], Status, **opts
745
+ attach_function :amqp_simple_wait_method, [ConnectionState, Channel, MethodNumber, Method.ptr], Status, **opts
746
+ attach_function :amqp_send_method, [ConnectionState, Channel, MethodNumber, Method.ptr], Status, **opts
747
+
748
+ attach_function :amqp_simple_rpc, [ConnectionState, Channel, MethodNumber, :pointer, :pointer], RpcReply.by_value, **opts
749
+ attach_function :amqp_simple_rpc_decoded, [ConnectionState, Channel, MethodNumber, MethodNumber, :pointer], :pointer, **opts
750
+ attach_function :amqp_get_rpc_reply, [ConnectionState], RpcReply.by_value, **opts
751
+ attach_function :amqp_login, [ConnectionState, :string, :int, :int, :int, SaslMethod, :varargs], RpcReply.by_value, **opts
752
+ attach_function :amqp_login_with_properties, [ConnectionState, :string, :int, :int, :int, Table.ptr, SaslMethod, :varargs], RpcReply.by_value, **opts
753
+ attach_function :amqp_channel_close, [ConnectionState, Channel, :int], RpcReply.by_value, **opts
754
+ attach_function :amqp_connection_close, [ConnectionState, :int], RpcReply.by_value, **opts
755
+
756
+ attach_function :amqp_basic_publish, [ConnectionState, Channel, Bytes, Bytes, Boolean, Boolean, BasicProperties.ptr, Bytes], RpcReply.by_value, **opts
757
+
758
+ attach_function :amqp_basic_get, [ConnectionState, Channel, Bytes, Boolean], Status, **opts
759
+ attach_function :amqp_basic_ack, [ConnectionState, Channel, :uint64, Boolean], Status, **opts
760
+ attach_function :amqp_basic_reject, [ConnectionState, Channel, :uint64, Boolean], Status, **opts
761
+ attach_function :amqp_basic_nack, [ConnectionState, Channel, :uint64, Boolean, Boolean], Status, **opts
693
762
 
694
763
  attach_function :amqp_data_in_buffer, [ConnectionState], Boolean, **opts
695
764
 
696
765
  attach_function :amqp_error_string, [:int], :string, **opts
697
766
  attach_function :amqp_error_string2, [:int], :string, **opts
698
767
 
699
- attach_function :amqp_decode_table, [Bytes, :pointer, :pointer, :pointer], :int, **opts
700
- attach_function :amqp_encode_table, [Bytes, :pointer, :pointer], :int, **opts
701
- attach_function :amqp_table_clone, [:pointer, :pointer, :pointer], :int, **opts
768
+ attach_function :amqp_decode_table, [Bytes, Pool.ptr, Table.ptr, :pointer], Status, **opts
769
+ attach_function :amqp_encode_table, [Bytes, Table.ptr, :pointer], Status, **opts
770
+ attach_function :amqp_table_clone, [Table.ptr, Table.ptr, Pool.ptr], Status, **opts
702
771
 
703
772
  class Message < ::FFI::Struct
704
773
  layout :properties, BasicProperties,
@@ -706,8 +775,8 @@ module RabbitMQ
706
775
  :pool, Pool
707
776
  end
708
777
 
709
- attach_function :amqp_read_message, [ConnectionState, Channel, :pointer, :int], RpcReply, **opts
710
- attach_function :amqp_destroy_message, [:pointer], :void, **opts
778
+ attach_function :amqp_read_message, [ConnectionState, Channel, Message.ptr, :int], RpcReply.by_value, **opts
779
+ attach_function :amqp_destroy_message, [Message.ptr], :void, **opts
711
780
 
712
781
  class Envelope < ::FFI::Struct
713
782
  layout :channel, Channel,
@@ -719,8 +788,8 @@ module RabbitMQ
719
788
  :message, Message
720
789
  end
721
790
 
722
- attach_function :amqp_consume_message, [ConnectionState, :pointer, :pointer, :int], RpcReply, **opts
723
- attach_function :amqp_destroy_envelope, [:pointer], :void, **opts
791
+ attach_function :amqp_consume_message, [ConnectionState, Envelope.ptr, Timeval.ptr, :int], RpcReply.by_value, **opts
792
+ attach_function :amqp_destroy_envelope, [Envelope.ptr], :void, **opts
724
793
 
725
794
  class ConnectionInfo < ::FFI::Struct
726
795
  layout :user, :string,
@@ -731,13 +800,23 @@ module RabbitMQ
731
800
  :ssl, Boolean
732
801
  end
733
802
 
734
- attach_function :amqp_default_connection_info, [:pointer], :void, **opts
735
- attach_function :amqp_parse_url, [:string, :pointer], :int, **opts
736
- attach_function :amqp_socket_open, [:pointer, :string, :int], :int, **opts
737
- attach_function :amqp_socket_open_noblock, [:pointer, :string, :int, :pointer], :int, **opts
738
- attach_function :amqp_socket_get_sockfd, [:pointer], :int, **opts
739
- attach_function :amqp_get_socket, [ConnectionState], :pointer, **opts
740
- attach_function :amqp_get_server_properties, [ConnectionState], Table, **opts
803
+ attach_function :amqp_default_connection_info, [ConnectionInfo.ptr], :void, **opts
804
+ attach_function :amqp_parse_url, [:pointer, ConnectionInfo.ptr], Status, **opts
805
+ attach_function :amqp_socket_open, [:pointer, :string, :int], Status, **opts
806
+ attach_function :amqp_socket_open_noblock, [:pointer, :string, :int, Timeval.ptr], Status, **opts
807
+ attach_function :amqp_socket_get_sockfd, [:pointer], :int, **opts
808
+ attach_function :amqp_get_socket, [ConnectionState], :pointer, **opts
809
+ attach_function :amqp_get_server_properties, [ConnectionState], Table, **opts
810
+
811
+ attach_function :amqp_tcp_socket_new, [ConnectionState], :pointer, **opts
812
+ attach_function :amqp_tcp_socket_set_sockfd, [:pointer, :int], :void, **opts
813
+
814
+ attach_function :amqp_ssl_socket_new, [ConnectionState], :pointer, **opts
815
+ attach_function :amqp_ssl_socket_set_cacert, [:pointer, :string], Status, **opts
816
+ attach_function :amqp_ssl_socket_set_key, [:pointer, :string, :string], Status, **opts
817
+ attach_function :amqp_ssl_socket_set_key_buffer, [:pointer, :string, :pointer, :size_t], Status, **opts
818
+ attach_function :amqp_ssl_socket_set_verify, [:pointer, Boolean], :void, **opts
819
+ attach_function :amqp_set_initialize_ssl_library, [Boolean], :void, **opts
741
820
  end
742
821
  end
743
822
  end
@@ -0,0 +1,42 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class Error < RuntimeError
6
+ def initialize message=nil
7
+ @message = message
8
+ end
9
+
10
+ def message
11
+ if @message && status_message; "#{status_message} - #{@message}"
12
+ elsif @message; @message
13
+ elsif status_message; status_message
14
+ else; ""
15
+ end
16
+ end
17
+
18
+ def status_message
19
+ nil
20
+ end
21
+
22
+ @lookup_table = {}
23
+ class << self
24
+ attr_reader :lookup_table
25
+ end
26
+
27
+ def self.lookup status
28
+ lookup_table.fetch(status)
29
+ end
30
+
31
+ FFI::Status.symbols.each do |status|
32
+ message = RabbitMQ::FFI.amqp_error_string2(status)
33
+ const_name = status.to_s.gsub(/((?:\A\w)|(?:_\w))/) { |x| x[-1].upcase }
34
+
35
+ kls = Class.new(Error) { define_method(:status_message) { message } }
36
+ lookup_table[status] = kls
37
+ const_set const_name, kls
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module RabbitMQ
3
+ module FFI
4
+
5
+ class ConnectionInfo
6
+ def to_h
7
+ members.map { |k| [k, self[k]] }.to_h
8
+ end
9
+ end
10
+
11
+ class Bytes
12
+ def to_s
13
+ ::FFI::Pointer.new(self[:bytes]).read_bytes(self[:len])
14
+ end
15
+
16
+ def self.from_s(str)
17
+ size = str.bytesize
18
+ ptr = Util.mem_ptr(size, release: false)
19
+ ptr.write_string(str)
20
+
21
+ bytes = new
22
+ bytes[:len] = str.bytesize
23
+ bytes[:bytes] = Util.mem_ptr(str.bytesize, release: false)
24
+ bytes
25
+ end
26
+ end
27
+
28
+ class FieldValue
29
+ private def value_member(kind)
30
+ case kind
31
+ when :utf8; :bytes
32
+ when :timestamp; :u64
33
+ else kind
34
+ end
35
+ end
36
+
37
+ def to_value
38
+ kind = self[:kind]
39
+ value = self[:value][value_member(kind)]
40
+ case kind
41
+ when :bytes; value.to_s
42
+ when :utf8; value.to_s.force_encoding(Encoding::UTF_8)
43
+ when :timestamp; Time.at(value / 1000.0)
44
+ when :table; value.to_h
45
+ when :array; value.to_array_not_yet_implemented!
46
+ when :decimal; value.to_value_not_yet_implemented!
47
+ else value
48
+ end
49
+ end
50
+ end
51
+
52
+ class Table
53
+ def to_h
54
+ entry_ptr = self[:entries]
55
+ entries = self[:num_entries].times.map { |i|
56
+ entry = FFI::TableEntry.new(entry_ptr + i * FFI::TableEntry.size)
57
+ [entry[:key].to_s, entry[:value].to_value]
58
+ }.to_h
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,36 @@
1
+
2
+ class RabbitMQ::FFI::Error < RuntimeError; end
3
+
4
+ module RabbitMQ::Util
5
+ class << self
6
+
7
+ def error_check action, status
8
+ return if status == :ok
9
+ raise RabbitMQ::FFI::Error.lookup(status), "while #{action}"
10
+ end
11
+
12
+ def null_check action, obj
13
+ return unless obj.nil?
14
+ raise RabbitMQ::FFI::Error, "while #{action} - got unexpected null"
15
+ end
16
+
17
+ def mem_ptr size, count: 1, clear: true, release: true
18
+ ptr = ::FFI::MemoryPointer.new(size, count, clear)
19
+ ptr.autorelease = false unless release
20
+ ptr
21
+ end
22
+
23
+ def arg_ptr type, **kwargs
24
+ type = ::FFI::TypeDefs[type] if type.is_a?(Symbol)
25
+ mem_ptr(type.size, clear: false, **kwargs)
26
+ end
27
+
28
+ def strdup_ptr str, **kwargs
29
+ str = str + "\x00"
30
+ ptr = mem_ptr(str.bytesize, **kwargs)
31
+ ptr.write_string(str)
32
+ ptr
33
+ end
34
+
35
+ end
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rabbitmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe McIlvain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-29 00:00:00.000000000 Z
11
+ date: 2015-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -111,12 +111,19 @@ dependencies:
111
111
  description: A Ruby RabbitMQ client library based on FFI bindings for librabbitmq.
112
112
  email: joe.eli.mac@gmail.com
113
113
  executables: []
114
- extensions: []
114
+ extensions:
115
+ - ext/rabbitmq/Rakefile
115
116
  extra_rdoc_files: []
116
117
  files:
118
+ - LICENSE
117
119
  - README.md
120
+ - ext/rabbitmq/Rakefile
118
121
  - lib/rabbitmq.rb
122
+ - lib/rabbitmq/connection.rb
119
123
  - lib/rabbitmq/ffi.rb
124
+ - lib/rabbitmq/ffi/error.rb
125
+ - lib/rabbitmq/ffi/ext.rb
126
+ - lib/rabbitmq/util.rb
120
127
  homepage: https://github.com/jemc/rabbitmq/
121
128
  licenses:
122
129
  - MIT