fotonauts-bunny 0.4.0

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