fotonauts-bunny 0.4.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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Duncan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,52 @@
1
+ = Bunny: A synchronous Ruby AMQP client
2
+
3
+ *GitHub* *repo*: http://github.com/celldee/bunny
4
+ *Rubyforge*: http://rubyforge.org/projects/bunny-amqp
5
+ *Twitter*: http://twitter.com/bunny_amqp
6
+ *Google* *Group*: http://groups.google.com/group/bunny-amqp
7
+
8
+ === DESCRIPTION:
9
+
10
+ Bunny is an AMQP[http://www.amqp.org] (Advanced Message Queuing Protocol) client, written in Ruby, that is intended to allow you to interact with AMQP-compliant message brokers/servers such as RabbitMQ[http://www.rabbitmq.com] in a synchronous fashion.
11
+
12
+ It is based on a great deal of useful code from amqp[http://github.com/tmm1/amqp] by Aman Gupta and Carrot[http://github.com/famoseagle/carrot] by Amos Elliston.
13
+
14
+ You can use Bunny to -
15
+
16
+ * Create and delete exchanges
17
+ * Create and delete queues
18
+ * Publish and consume messages
19
+
20
+ Bunny is known to work with RabbitMQ version 1.5.4 and version 0-8 of the AMQP specification.
21
+
22
+ === INSTALL:
23
+
24
+ *Rubyforge*: <tt>gem install bunny</tt>
25
+
26
+ *GitHub*: <tt>gem install celldee-bunny</tt>
27
+
28
+ === QUICK START:
29
+
30
+ require 'bunny'
31
+
32
+ b = Bunny.new(:logging => true)
33
+
34
+ # start a communication session with the amqp server
35
+ b.start
36
+
37
+ # declare a queue
38
+ q = b.queue('test1')
39
+
40
+ # publish a message to the queue
41
+ q.publish('Hello everybody!')
42
+
43
+ # get message from the queue
44
+ msg = q.pop
45
+
46
+ puts 'This is the message: ' + msg + "\n\n"
47
+
48
+ # close the connection
49
+ b.stop
50
+
51
+ === OTHER:
52
+ Please see the _examples_ directory for additional usage information.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ task :spec do
2
+ require 'spec/rake/spectask'
3
+ Spec::Rake::SpecTask.new do |t|
4
+ t.spec_opts = ['--color']
5
+ end
6
+ end
data/bunny.gemspec ADDED
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{bunny}
3
+ s.version = "0.4.0"
4
+
5
+ s.authors = ["Chris Duncan"]
6
+ s.date = %q{2009-05-15}
7
+ s.description = %q{Another synchronous Ruby AMQP client}
8
+ s.email = %q{celldee@gmail.com}
9
+ s.rubyforge_project = %q{bunny-amqp}
10
+ s.has_rdoc = true
11
+ s.extra_rdoc_files = [ "README" ]
12
+ s.rdoc_options = [ "--main", "README" ]
13
+ s.homepage = %q{http://github.com/celldee/bunny}
14
+ s.summary = %q{A synchronous Ruby AMQP client that enables interaction with AMQP-compliant brokers/servers.}
15
+ s.files = ["LICENSE",
16
+ "README",
17
+ "Rakefile",
18
+ "bunny.gemspec",
19
+ "examples/simple.rb",
20
+ "examples/simple_ack.rb",
21
+ "examples/simple_consumer.rb",
22
+ "examples/simple_fanout.rb",
23
+ "examples/simple_publisher.rb",
24
+ "examples/simple_topic.rb",
25
+ "lib/bunny.rb",
26
+ "lib/bunny/client.rb",
27
+ "lib/bunny/exchange.rb",
28
+ "lib/bunny/queue.rb",
29
+ "lib/qrack/client.rb",
30
+ "lib/qrack/protocol/protocol.rb",
31
+ "lib/qrack/protocol/spec.rb",
32
+ "lib/qrack/qrack.rb",
33
+ "lib/qrack/transport/buffer.rb",
34
+ "lib/qrack/transport/frame.rb",
35
+ "spec/bunny_spec.rb",
36
+ "spec/exchange_spec.rb",
37
+ "spec/queue_spec.rb"]
38
+ end
@@ -0,0 +1,30 @@
1
+ # simple.rb
2
+
3
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
4
+ # and that it is running on 'localhost'.
5
+
6
+ # If this is not the case, please change the 'Bunny.new' call below to include
7
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
+
9
+ $:.unshift File.dirname(__FILE__) + '/../lib'
10
+
11
+ require 'bunny'
12
+
13
+ b = Bunny.new(:logging => true)
14
+
15
+ # start a communication session with the amqp server
16
+ b.start
17
+
18
+ # declare a queue
19
+ q = b.queue('test1')
20
+
21
+ # publish a message to the queue
22
+ q.publish('Hello everybody!')
23
+
24
+ # get message from the queue
25
+ msg = q.pop
26
+
27
+ puts 'This is the message: ' + msg + "\n\n"
28
+
29
+ # close the client connection
30
+ b.stop
@@ -0,0 +1,33 @@
1
+ # simple_ack.rb
2
+
3
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
4
+ # and that it is running on 'localhost'.
5
+
6
+ # If this is not the case, please change the 'Bunny.new' call below to include
7
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
+
9
+ $:.unshift File.dirname(__FILE__) + '/../lib'
10
+
11
+ require 'bunny'
12
+
13
+ b = Bunny.new(:logging => true)
14
+
15
+ # start a communication session with the amqp server
16
+ b.start
17
+
18
+ # declare a queue
19
+ q = b.queue('test1')
20
+
21
+ # publish a message to the queue
22
+ q.publish('Testing acknowledgements')
23
+
24
+ # get message from the queue
25
+ msg = q.pop(:ack => true)
26
+
27
+ # acknowledge receipt of message
28
+ q.ack
29
+
30
+ puts 'This is the message: ' + msg + "\n\n"
31
+
32
+ # close the client connection
33
+ b.stop
@@ -0,0 +1,55 @@
1
+ # consumer.rb
2
+
3
+ # N.B. To be used in conjunction with simple_publisher.rb
4
+
5
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
6
+ # and that it is running on 'localhost'.
7
+
8
+ # If this is not the case, please change the 'Bunny.new' call below to include
9
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
10
+
11
+ # How this example works
12
+ #=======================
13
+ #
14
+ # Open up two console windows start this program in one of them by typing -
15
+ #
16
+ # ruby simple_consumer.rb
17
+ #
18
+ # Then switch to the other console window and type -
19
+ #
20
+ # ruby simple_publisher.rb
21
+ #
22
+ # A message will be printed out by the simple_consumer and it will wait for the next message
23
+ #
24
+ # Run simple_publisher 3 more times. After the last run simple_consumer will stop.
25
+
26
+ $:.unshift File.dirname(__FILE__) + '/../lib'
27
+
28
+ require 'bunny'
29
+
30
+ b = Bunny.new(:logging => true)
31
+
32
+ # start a communication session with the amqp server
33
+ b.start
34
+
35
+ # create/get queue
36
+ q = b.queue('po_box')
37
+
38
+ # create/get exchange
39
+ exch = b.exchange('sorting_room')
40
+
41
+ # bind queue to exchange
42
+ q.bind(exch, :key => 'fred')
43
+
44
+ # initialize counter
45
+ i = 1
46
+
47
+ # subscribe to queue
48
+ q.subscribe(:consumer_tag => 'testtag1') do |msg|
49
+ puts i.to_s + ': ' + msg
50
+ i+=1
51
+ q.unsubscribe(:consumer_tag => 'testtag1') if i == 5
52
+ end
53
+
54
+ # close the connection
55
+ b.stop
@@ -0,0 +1,39 @@
1
+ # fanout.rb
2
+
3
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
4
+ # and that it is running on 'localhost'.
5
+
6
+ # If this is not the case, please change the 'Bunny.new' call below to include
7
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
+
9
+ $:.unshift File.dirname(__FILE__) + '/../lib'
10
+
11
+ require 'bunny'
12
+
13
+ b = Bunny.new(:logging => true)
14
+
15
+ # start a communication session with the amqp server
16
+ b.start
17
+
18
+ # declare queues
19
+ q1 = b.queue('test_fan1')
20
+ q2 = b.queue('test_fan2')
21
+
22
+ # create a fanout exchange
23
+ exch = b.exchange('test_fan', :type => :fanout)
24
+
25
+ # bind the queues to the exchange
26
+ q1.bind(exch)
27
+ q2.bind(exch)
28
+
29
+ # publish a message to the exchange
30
+ exch.publish('This message will be fanned out')
31
+
32
+ # get message from the queues
33
+ msg = q1.pop
34
+ puts 'This is the message from q1: ' + msg + "\n\n"
35
+ msg = q2.pop
36
+ puts 'This is the message from q2: ' + msg + "\n\n"
37
+
38
+ # close the client connection
39
+ b.stop
@@ -0,0 +1,27 @@
1
+ # simple_publisher.rb
2
+
3
+ # N.B. To be used in conjunction with simple_consumer.rb. See simple_consumer.rb for explanation.
4
+
5
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
6
+ # and that it is running on 'localhost'.
7
+
8
+ # If this is not the case, please change the 'Bunny.new' call below to include
9
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
10
+
11
+ $:.unshift File.dirname(__FILE__) + '/../lib'
12
+
13
+ require 'bunny'
14
+
15
+ b = Bunny.new(:logging => true)
16
+
17
+ # start a communication session with the amqp server
18
+ b.start
19
+
20
+ # create/get exchange
21
+ exch = b.exchange('sorting_room')
22
+
23
+ # publish message to exchange
24
+ exch.publish('This is a message from the publisher', :key => 'fred')
25
+
26
+ # message should now be picked up by the consumer so we can stop
27
+ b.stop
@@ -0,0 +1,59 @@
1
+ # simple_topic.rb
2
+
3
+ # Assumes that target message broker/server has a user called 'guest' with a password 'guest'
4
+ # and that it is running on 'localhost'.
5
+
6
+ # If this is not the case, please change the 'Bunny.new' call below to include
7
+ # the relevant arguments e.g. b = Bunny.new(:user => 'john', :pass => 'doe', :host => 'foobar')
8
+
9
+ $:.unshift File.dirname(__FILE__) + '/../lib'
10
+
11
+ require 'bunny'
12
+
13
+ b = Bunny.new
14
+
15
+ # start a communication session with the amqp server
16
+ b.start
17
+
18
+ # declare queues
19
+ soccer = b.queue('topic_soccer')
20
+ cricket = b.queue('topic_cricket')
21
+ rugby = b.queue('topic_rugby')
22
+ allsport = b.queue('topic_allsport')
23
+
24
+ # create a topic exchange
25
+ sports_results = b.exchange('sports_results', :type => :topic)
26
+
27
+ # bind the queues to the exchange
28
+ soccer.bind(sports_results, :key => 'soccer.*')
29
+ cricket.bind(sports_results, :key => 'cricket.*')
30
+ rugby.bind(sports_results, :key => 'rugby.*')
31
+ allsport.bind(sports_results, :key => '*.result')
32
+
33
+ # publish messages to the exchange
34
+ sports_results.publish('Manchester United 1 : Hull City 4', :key => 'soccer.result')
35
+ sports_results.publish('England beat Australia by 5 wickets in first test', :key => 'cricket.result')
36
+ sports_results.publish('British Lions 15 : South Africa 12', :key => 'rugby.result')
37
+
38
+ # get message from the queues
39
+
40
+ # soccer queue got the soccer message
41
+ msg = soccer.pop
42
+ puts 'This is a message from the soccer q: ' + msg + "\n\n"
43
+
44
+ # cricket queue got the cricket message
45
+ msg = cricket.pop
46
+ puts 'This is a message from the cricket q: ' + msg + "\n\n"
47
+
48
+ # rugby queue got the rugby message
49
+ msg = rugby.pop
50
+ puts 'This is a message from the rugby q: ' + msg + "\n\n"
51
+
52
+ # allsport queue got all of the messages
53
+ until msg == :queue_empty do
54
+ msg = allsport.pop
55
+ puts 'This is a message from the allsport q: ' + msg + "\n\n" unless msg == :queue_empty
56
+ end
57
+
58
+ # close the client connection
59
+ b.stop
@@ -0,0 +1,324 @@
1
+ module Bunny
2
+
3
+ =begin rdoc
4
+
5
+ === DESCRIPTION:
6
+
7
+ The Client class provides the major Bunny API methods.
8
+
9
+ =end
10
+
11
+ class Client < Qrack::Client
12
+ CONNECT_TIMEOUT = 1.0
13
+ RETRY_DELAY = 10.0
14
+
15
+ attr_reader :status, :host, :vhost, :port
16
+ attr_accessor :channel, :logging, :exchanges, :queues, :ticket
17
+
18
+ =begin rdoc
19
+
20
+ === DESCRIPTION:
21
+
22
+ Sets up a Bunny::Client object ready for connection to a broker/server. _Client_._status_ is set to
23
+ <tt>:not_connected</tt>.
24
+
25
+ ==== OPTIONS:
26
+
27
+ * <tt>:host => '_hostname_' (default = 'localhost')</tt>
28
+ * <tt>:port => _portno_ (default = 5672)</tt>
29
+ * <tt>:vhost => '_vhostname_' (default = '/')</tt>
30
+ * <tt>:user => '_username_' (default = 'guest')</tt>
31
+ * <tt>:pass => '_password_' (default = 'guest')</tt>
32
+ * <tt>:logging => true or false (_default_)</tt> - If set to _true_, session information is sent
33
+ to STDOUT.
34
+ * <tt>:insist => true or false (_default_)</tt> - In a configuration with multiple load-sharing
35
+ servers, the server may respond to a Connection.Open method with a Connection.Redirect. The insist
36
+ option, if set to _true_, tells the server that the client is insisting on a connection to the
37
+ specified server.
38
+
39
+ =end
40
+
41
+ def initialize(opts = {})
42
+ @host = opts[:host] || 'localhost'
43
+ @port = opts[:port] || Qrack::Protocol::PORT
44
+ @user = opts[:user] || 'guest'
45
+ @pass = opts[:pass] || 'guest'
46
+ @vhost = opts[:vhost] || '/'
47
+ @logging = opts[:logging] || false
48
+ @insist = opts[:insist]
49
+ @status = :not_connected
50
+ end
51
+
52
+ =begin rdoc
53
+
54
+ === DESCRIPTION:
55
+
56
+ Declares an exchange to the broker/server. If the exchange does not exist, a new one is created
57
+ using the arguments passed in. If the exchange already exists, a reference to it is created, provided
58
+ that the arguments passed in do not conflict with the existing attributes of the exchange. If an error
59
+ occurs a _Bunny_::_ProtocolError_ is raised.
60
+
61
+ ==== OPTIONS:
62
+
63
+ * <tt>:type => one of :direct (_default_), :fanout, :topic, :headers</tt>
64
+ * <tt>:passive => true or false</tt> - If set to _true_, the server will not create the exchange.
65
+ The client can use this to check whether an exchange exists without modifying the server state.
66
+ * <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new exchange, the exchange
67
+ will be marked as durable. Durable exchanges remain active when a server restarts. Non-durable
68
+ exchanges (transient exchanges) are purged if/when a server restarts.
69
+ * <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the exchange is deleted
70
+ when all queues have finished using it.
71
+ * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
72
+
73
+ ==== RETURNS:
74
+
75
+ Exchange
76
+
77
+ =end
78
+
79
+ def exchange(name, opts = {})
80
+ exchanges[name] ||= Bunny::Exchange.new(self, name, opts)
81
+ end
82
+
83
+ =begin rdoc
84
+
85
+ === DESCRIPTION:
86
+
87
+ Returns hash of exchanges declared by Bunny.
88
+
89
+ =end
90
+
91
+ def exchanges
92
+ @exchanges ||= {}
93
+ end
94
+
95
+ =begin rdoc
96
+
97
+ === DESCRIPTION:
98
+
99
+ Declares a queue to the broker/server. If the queue does not exist, a new one is created
100
+ using the arguments passed in. If the queue already exists, a reference to it is created, provided
101
+ that the arguments passed in do not conflict with the existing attributes of the queue. If an error
102
+ occurs a _Bunny_::_ProtocolError_ is raised.
103
+
104
+ ==== OPTIONS:
105
+
106
+ * <tt>:passive => true or false (_default_)</tt> - If set to _true_, the server will not create
107
+ the queue. The client can use this to check whether a queue exists without modifying the server
108
+ state.
109
+ * <tt>:durable => true or false (_default_)</tt> - If set to _true_ when creating a new queue, the
110
+ queue will be marked as durable. Durable queues remain active when a server restarts. Non-durable
111
+ queues (transient queues) are purged if/when a server restarts. Note that durable queues do not
112
+ necessarily hold persistent messages, although it does not make sense to send persistent messages
113
+ to a transient queue.
114
+ * <tt>:exclusive => true or false (_default_)</tt> - If set to _true_, requests an exclusive queue.
115
+ Exclusive queues may only be consumed from by the current connection. Setting the 'exclusive'
116
+ flag always implies 'auto-delete'.
117
+ * <tt>:auto_delete => true or false (_default_)</tt> - If set to _true_, the queue is deleted
118
+ when all consumers have finished using it. Last consumer can be cancelled either explicitly
119
+ or because its channel is closed. If there has never been a consumer on the queue, it is not
120
+ deleted.
121
+ * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
122
+
123
+ ==== RETURNS:
124
+
125
+ Queue
126
+
127
+ =end
128
+
129
+ def queue(name, opts = {})
130
+ queues[name] ||= Bunny::Queue.new(self, name, opts)
131
+ end
132
+
133
+ =begin rdoc
134
+
135
+ === DESCRIPTION:
136
+
137
+ Returns hash of queues declared by Bunny.
138
+
139
+ =end
140
+
141
+ def queues
142
+ @queues ||= {}
143
+ end
144
+
145
+ def send_frame(*args)
146
+ args.each do |data|
147
+ data.ticket = ticket if ticket and data.respond_to?(:ticket=)
148
+ data = data.to_frame(channel) unless data.is_a?(Qrack::Transport::Frame)
149
+ data.channel = channel
150
+
151
+ log :send, data
152
+ write(data.to_s)
153
+ end
154
+ nil
155
+ end
156
+
157
+ def next_frame
158
+ frame = Qrack::Transport::Frame.parse(buffer)
159
+ log :received, frame
160
+ frame
161
+ end
162
+
163
+ def next_method
164
+ next_payload
165
+ end
166
+
167
+ def next_payload
168
+ frame = next_frame
169
+ frame and frame.payload
170
+ end
171
+
172
+ =begin rdoc
173
+
174
+ === DESCRIPTION:
175
+
176
+ Closes the current communication channel and connection. If an error occurs a
177
+ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:not_connected</tt>.
178
+
179
+ ==== RETURNS:
180
+
181
+ <tt>:not_connected</tt> if successful.
182
+
183
+ =end
184
+
185
+ def close
186
+ send_frame(
187
+ Qrack::Protocol::Channel::Close.new(:reply_code => 200, :reply_text => 'bye', :method_id => 0, :class_id => 0)
188
+ )
189
+ raise Bunny::ProtocolError, "Error closing channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::CloseOk)
190
+
191
+ self.channel = 0
192
+ send_frame(
193
+ Qrack::Protocol::Connection::Close.new(:reply_code => 200, :reply_text => 'Goodbye', :class_id => 0, :method_id => 0)
194
+ )
195
+ raise Bunny::ProtocolError, "Error closing connection" unless next_method.is_a?(Qrack::Protocol::Connection::CloseOk)
196
+
197
+ close_socket
198
+ end
199
+
200
+ alias stop close
201
+
202
+ def read(*args)
203
+ send_command(:read, *args)
204
+ end
205
+
206
+ def write(*args)
207
+ send_command(:write, *args)
208
+ end
209
+
210
+ =begin rdoc
211
+
212
+ === DESCRIPTION:
213
+
214
+ Opens a communication channel and starts a connection. If an error occurs, a
215
+ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:connected</tt>.
216
+
217
+ ==== RETURNS:
218
+
219
+ <tt>:connected</tt> if successful.
220
+
221
+ =end
222
+
223
+ def start_session
224
+ @channel = 0
225
+ write(Qrack::Protocol::HEADER)
226
+ write([1, 1, Qrack::Protocol::VERSION_MAJOR, Qrack::Protocol::VERSION_MINOR].pack('C4'))
227
+ raise Bunny::ProtocolError, 'Connection initiation failed' unless next_method.is_a?(Qrack::Protocol::Connection::Start)
228
+
229
+ send_frame(
230
+ Qrack::Protocol::Connection::StartOk.new(
231
+ {:platform => 'Ruby', :product => 'Bunny', :information => 'http://github.com/celldee/bunny', :version => VERSION},
232
+ 'AMQPLAIN',
233
+ {:LOGIN => @user, :PASSWORD => @pass},
234
+ 'en_US'
235
+ )
236
+ )
237
+
238
+ method = next_method
239
+ raise Bunny::ProtocolError, "Connection failed - user: #{@user}, pass: #{@pass}" if method.nil?
240
+
241
+ if method.is_a?(Qrack::Protocol::Connection::Tune)
242
+ send_frame(
243
+ Qrack::Protocol::Connection::TuneOk.new( :channel_max => 0, :frame_max => 131072, :heartbeat => 0)
244
+ )
245
+ end
246
+
247
+ send_frame(
248
+ Qrack::Protocol::Connection::Open.new(:virtual_host => @vhost, :capabilities => '', :insist => @insist)
249
+ )
250
+ raise Bunny::ProtocolError, 'Cannot open connection' unless next_method.is_a?(Qrack::Protocol::Connection::OpenOk)
251
+
252
+ @channel = 1
253
+ send_frame(Qrack::Protocol::Channel::Open.new)
254
+ raise Bunny::ProtocolError, "Cannot open channel #{channel}" unless next_method.is_a?(Qrack::Protocol::Channel::OpenOk)
255
+
256
+ send_frame(
257
+ Qrack::Protocol::Access::Request.new(:realm => '/data', :read => true, :write => true, :active => true, :passive => true)
258
+ )
259
+ method = next_method
260
+ raise Bunny::ProtocolError, 'Access denied' unless method.is_a?(Qrack::Protocol::Access::RequestOk)
261
+ self.ticket = method.ticket
262
+
263
+ # return status
264
+ status
265
+ end
266
+
267
+ alias start start_session
268
+
269
+ private
270
+
271
+ def buffer
272
+ @buffer ||= Qrack::Transport::Buffer.new(self)
273
+ end
274
+
275
+ def send_command(cmd, *args)
276
+ begin
277
+ timeout(1.5) do
278
+ socket.__send__(cmd, *args)
279
+ end
280
+ rescue => e
281
+ @status = :not_connected
282
+ raise Bunny::ServerDownError, e.message
283
+ end
284
+ end
285
+
286
+ def socket
287
+ return @socket if @socket and (@status == :connected) and not @socket.closed?
288
+
289
+ begin
290
+ @status = :not_connected
291
+
292
+ # Attempt to connect.
293
+ @socket = timeout(CONNECT_TIMEOUT) do
294
+ TCPSocket.new(host, port)
295
+ end
296
+
297
+ if Socket.constants.include? 'TCP_NODELAY'
298
+ @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
299
+ end
300
+ @status = :connected
301
+ rescue => e
302
+ @status = :not_connected
303
+ raise Bunny::ServerDownError, e.message
304
+ end
305
+
306
+ @socket
307
+ end
308
+
309
+ def close_socket(reason=nil)
310
+ # Close the socket. The server is not considered dead.
311
+ @socket.close if @socket and not @socket.closed?
312
+ @socket = nil
313
+ @status = :not_connected
314
+ end
315
+
316
+ def log(*args)
317
+ return unless logging
318
+ require 'pp'
319
+ pp args
320
+ puts
321
+ end
322
+
323
+ end
324
+ end