bunny 0.8.0 → 0.9.0.pre1

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.
Files changed (91) hide show
  1. data/.gitignore +7 -1
  2. data/.travis.yml +14 -4
  3. data/ChangeLog.md +72 -0
  4. data/Gemfile +17 -11
  5. data/README.md +82 -0
  6. data/bunny.gemspec +6 -13
  7. data/examples/connection/heartbeat.rb +17 -0
  8. data/lib/bunny.rb +40 -56
  9. data/lib/bunny/channel.rb +615 -19
  10. data/lib/bunny/channel_id_allocator.rb +59 -0
  11. data/lib/bunny/compatibility.rb +24 -0
  12. data/lib/bunny/concurrent/condition.rb +63 -0
  13. data/lib/bunny/consumer.rb +42 -26
  14. data/lib/bunny/consumer_tag_generator.rb +22 -0
  15. data/lib/bunny/consumer_work_pool.rb +67 -0
  16. data/lib/bunny/exceptions.rb +128 -0
  17. data/lib/bunny/exchange.rb +131 -136
  18. data/lib/bunny/framing.rb +53 -0
  19. data/lib/bunny/heartbeat_sender.rb +59 -0
  20. data/lib/bunny/main_loop.rb +70 -0
  21. data/lib/bunny/message_metadata.rb +126 -0
  22. data/lib/bunny/queue.rb +102 -275
  23. data/lib/bunny/session.rb +478 -0
  24. data/lib/bunny/socket.rb +44 -0
  25. data/lib/bunny/system_timer.rb +9 -9
  26. data/lib/bunny/transport.rb +179 -0
  27. data/lib/bunny/version.rb +1 -1
  28. data/spec/compatibility/queue_declare_spec.rb +40 -0
  29. data/spec/higher_level_api/integration/basic_ack_spec.rb +54 -0
  30. data/spec/higher_level_api/integration/basic_consume_spec.rb +51 -0
  31. data/spec/higher_level_api/integration/basic_get_spec.rb +47 -0
  32. data/spec/higher_level_api/integration/basic_nack_spec.rb +39 -0
  33. data/spec/higher_level_api/integration/basic_publish_spec.rb +105 -0
  34. data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -0
  35. data/spec/higher_level_api/integration/basic_recover_spec.rb +18 -0
  36. data/spec/higher_level_api/integration/basic_reject_spec.rb +53 -0
  37. data/spec/higher_level_api/integration/basic_return_spec.rb +33 -0
  38. data/spec/higher_level_api/integration/channel_close_spec.rb +29 -0
  39. data/spec/higher_level_api/integration/channel_flow_spec.rb +24 -0
  40. data/spec/higher_level_api/integration/channel_open_spec.rb +57 -0
  41. data/spec/higher_level_api/integration/channel_open_stress_spec.rb +22 -0
  42. data/spec/higher_level_api/integration/confirm_select_spec.rb +19 -0
  43. data/spec/higher_level_api/integration/connection_spec.rb +340 -0
  44. data/spec/higher_level_api/integration/exchange_bind_spec.rb +31 -0
  45. data/spec/higher_level_api/integration/exchange_declare_spec.rb +183 -0
  46. data/spec/higher_level_api/integration/exchange_delete_spec.rb +37 -0
  47. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +40 -0
  48. data/spec/higher_level_api/integration/queue_bind_spec.rb +109 -0
  49. data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -0
  50. data/spec/higher_level_api/integration/queue_delete_spec.rb +38 -0
  51. data/spec/higher_level_api/integration/queue_purge_spec.rb +30 -0
  52. data/spec/higher_level_api/integration/queue_unbind_spec.rb +33 -0
  53. data/spec/higher_level_api/integration/tx_commit_spec.rb +21 -0
  54. data/spec/higher_level_api/integration/tx_rollback_spec.rb +21 -0
  55. data/spec/lower_level_api/integration/basic_cancel_spec.rb +57 -0
  56. data/spec/lower_level_api/integration/basic_consume_spec.rb +100 -0
  57. data/spec/spec_helper.rb +64 -0
  58. data/spec/unit/bunny_spec.rb +15 -0
  59. data/spec/unit/concurrent/condition_spec.rb +66 -0
  60. metadata +135 -93
  61. data/CHANGELOG +0 -21
  62. data/README.textile +0 -76
  63. data/Rakefile +0 -14
  64. data/examples/simple.rb +0 -32
  65. data/examples/simple_ack.rb +0 -35
  66. data/examples/simple_consumer.rb +0 -55
  67. data/examples/simple_fanout.rb +0 -41
  68. data/examples/simple_headers.rb +0 -42
  69. data/examples/simple_publisher.rb +0 -29
  70. data/examples/simple_topic.rb +0 -61
  71. data/ext/amqp-0.9.1.json +0 -389
  72. data/ext/config.yml +0 -4
  73. data/ext/qparser.rb +0 -426
  74. data/lib/bunny/client.rb +0 -370
  75. data/lib/bunny/subscription.rb +0 -92
  76. data/lib/qrack/amq-client-url.rb +0 -165
  77. data/lib/qrack/channel.rb +0 -20
  78. data/lib/qrack/client.rb +0 -247
  79. data/lib/qrack/errors.rb +0 -5
  80. data/lib/qrack/protocol/protocol.rb +0 -135
  81. data/lib/qrack/protocol/spec.rb +0 -525
  82. data/lib/qrack/qrack.rb +0 -20
  83. data/lib/qrack/queue.rb +0 -40
  84. data/lib/qrack/subscription.rb +0 -152
  85. data/lib/qrack/transport/buffer.rb +0 -305
  86. data/lib/qrack/transport/frame.rb +0 -102
  87. data/spec/spec_09/amqp_url_spec.rb +0 -19
  88. data/spec/spec_09/bunny_spec.rb +0 -76
  89. data/spec/spec_09/connection_spec.rb +0 -34
  90. data/spec/spec_09/exchange_spec.rb +0 -173
  91. data/spec/spec_09/queue_spec.rb +0 -240
@@ -1,92 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Bunny
4
-
5
- # Asks the server to start a "consumer", which is a transient request for messages from a specific
6
- # queue. Consumers last as long as the channel they were created on, or until the client cancels them
7
- # with an @unsubscribe@. Every time a message reaches the queue it is passed to the @blk@ for
8
- # processing. If error occurs, {Bunny::ProtocolError} is raised.
9
- #
10
- # @option opts [String] :consumer_tag
11
- # Specifies the identifier for the consumer. The consumer tag is
12
- # local to a connection, so two clients can use the same consumer tags.
13
- # If this option is not specified a server generated name is used.
14
- #
15
- # @option opts [Boolean] :ack (false)
16
- # If set to @false@, the server does not expect an acknowledgement message
17
- # from the client. If set to @true, the server expects an acknowledgement
18
- # message from the client and will re-queue the message if it does not
19
- # receive one within a time specified by the server.
20
- #
21
- # @option opts [Boolean] :exclusive (false)
22
- # Request exclusive consumer access, meaning only this consumer can access the queue.
23
- #
24
- # @option opts [Boolean] :nowait (false)
25
- # Ignored by Bunny, always @false@.
26
- #
27
- # @option opts [Numeric] :timeout
28
- # The subscribe loop will continue to wait for messages
29
- # until terminated (Ctrl-C or kill command) or this timeout interval is reached.
30
- #
31
- # @option opts [Integer] :message_max
32
- # When the required number of messages is processed subscribe loop is exited.
33
- #
34
- # @option opts [IO] :cancellator (nil)
35
- # A cancellator can be used to for cancelling the subscribe loop from another
36
- # thread or from a signal handler. Whenever Bunny notices that this IO object has
37
- # become readable, the subscribe loop will be exited after the current message
38
- # has been processed.
39
- #
40
- # h2. Operation
41
- #
42
- # Passes a hash of message information to the block, if one has been supplied. The hash contains
43
- # :header, :payload and :delivery_details. The structure of the data is as follows -
44
- #
45
- # :header has instance variables -
46
- # @klass
47
- # @size
48
- # @weight
49
- # @properties is a hash containing -
50
- # :content_type
51
- # :delivery_mode
52
- # :priority
53
- #
54
- # :payload contains the message contents
55
- #
56
- # :delivery details is a hash containing -
57
- # :consumer_tag
58
- # :delivery_tag
59
- # :redelivered
60
- # :exchange
61
- # :routing_key
62
- #
63
- # If the :timeout option is specified then the subscription will automatically
64
- # cease if the given number of seconds passes with no message arriving.
65
- #
66
- # @example
67
- # my_queue.subscribe(timeout: 5) { |msg| puts msg[:payload] }
68
- # my_queue.subscribe(message_max: 10, ack: true) { |msg| puts msg[:payload] }
69
- class Subscription < Bunny::Consumer
70
-
71
- def setup_consumer
72
- subscription_options = {
73
- :deprecated_ticket => 0,
74
- :queue => queue.name,
75
- :consumer_tag => consumer_tag,
76
- :no_ack => !ack,
77
- :exclusive => exclusive,
78
- :nowait => false
79
- }.merge(@opts)
80
-
81
- client.send_frame(Qrack::Protocol::Basic::Consume.new(subscription_options))
82
-
83
- method = client.next_method
84
-
85
- client.check_response(method, Qrack::Protocol::Basic::ConsumeOk, "Error subscribing to queue #{queue.name}, got #{method}")
86
-
87
- @consumer_tag = method.consumer_tag
88
- end
89
-
90
- end
91
-
92
- end
@@ -1,165 +0,0 @@
1
- # encoding: utf-8
2
-
3
- ################################################################
4
- # DO NOT EDIT THIS FILE ! #
5
- # The file comes from https://github.com/ruby-amqp/amq-client, #
6
- # it's located in lib/amq/client/settings.rb, so if you want #
7
- # to make some changes, please do them in the amq-client repo. #
8
- ################################################################
9
-
10
- # TODO: When we start to work on porting Bunny on AMQ Client,
11
- # this file will become obsolete.
12
-
13
- require "uri"
14
-
15
- module AMQ
16
- module Client
17
- # @see AMQ::Client::Settings.configure
18
- module Settings
19
- # @private
20
- AMQP_PORTS = {"amqp" => 5672, "amqps" => 5671}.freeze
21
-
22
- # @private
23
- AMQPS = "amqps".freeze
24
-
25
- # Default connection settings used by AMQ clients
26
- #
27
- # @see AMQ::Client::Settings.configure
28
- def self.default
29
- @default ||= {
30
- # server
31
- :host => "127.0.0.1",
32
- :port => AMQ::Protocol::DEFAULT_PORT,
33
-
34
- # login
35
- :user => "guest",
36
- :pass => "guest",
37
- :vhost => "/",
38
-
39
- # connection timeout
40
- :timeout => nil,
41
-
42
- # logging
43
- :logging => false,
44
-
45
- # ssl
46
- :ssl => false,
47
-
48
- # broker
49
- # if you want to load broker-specific extensions
50
- :broker => nil,
51
-
52
- :frame_max => 131072
53
- }
54
- end
55
-
56
-
57
- def self.client_properties
58
- @client_properties ||= {
59
- :platform => ::RUBY_DESCRIPTION,
60
- :product => "AMQ Client",
61
- :information => "http://github.com/ruby-amqp/amq-client",
62
- :version => AMQ::Client::VERSION
63
- }
64
- end
65
-
66
-
67
- # Merges given configuration parameters with defaults and returns
68
- # the result.
69
- #
70
- # @param [Hash] Configuration parameters to use.
71
- #
72
- # @option settings [String] :host ("127.0.0.1") Hostname AMQ broker runs on.
73
- # @option settings [String] :port (5672) Port AMQ broker listens on.
74
- # @option settings [String] :vhost ("/") Virtual host to use.
75
- # @option settings [String] :user ("guest") Username to use for authentication.
76
- # @option settings [String] :pass ("guest") Password to use for authentication.
77
- # @option settings [String] :ssl (false) Should be use TLS (SSL) for connection?
78
- # @option settings [String] :timeout (nil) Connection timeout.
79
- # @option settings [String] :logging (false) Turns logging on or off.
80
- # @option settings [String] :broker (nil) Broker name (use if you intend to use broker-specific features).
81
- # @option settings [Fixnum] :frame_max (131072) Maximum frame size to use. If broker cannot support frames this large, broker's maximum value will be used instead.
82
- #
83
- # @return [Hash] Merged configuration parameters.
84
- def self.configure(settings = nil)
85
- case settings
86
- when Hash then
87
- if username = settings.delete(:username)
88
- settings[:user] ||= username
89
- end
90
-
91
- if password = settings.delete(:password)
92
- settings[:pass] ||= password
93
- end
94
-
95
-
96
- self.default.merge(settings)
97
- when String then
98
- settings = self.parse_amqp_url(settings)
99
- self.default.merge(settings)
100
- when NilClass then
101
- self.default
102
- end
103
- end
104
-
105
- # Parses AMQP connection URI and returns its components as a hash.
106
- #
107
- # h2. vhost naming schemes
108
- #
109
- # It is convenient to be able to specify the AMQP connection
110
- # parameters as a URI string, and various "amqp" URI schemes
111
- # exist. Unfortunately, there is no standard for these URIs, so
112
- # while the schemes share the basic idea, they differ in some
113
- # details. This implementation aims to encourage URIs that work
114
- # as widely as possible.
115
- #
116
- # The URI scheme should be "amqp", or "amqps" if SSL is required.
117
- #
118
- # The host, port, username and password are represented in the
119
- # authority component of the URI in the same way as in http URIs.
120
- #
121
- # The vhost is obtained from the first segment of the path, with the
122
- # leading slash removed. The path should contain only a single
123
- # segment (i.e, the only slash in it should be the leading one).
124
- # If the vhost is to include slashes or other reserved URI
125
- # characters, these should be percent-escaped.
126
- #
127
- # @example How vhost is parsed
128
- #
129
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com") # => vhost is nil, so default (/) will be used
130
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/") # => vhost is an empty string
131
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/%2Fvault") # => vhost is /vault
132
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/production") # => vhost is production
133
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/a.b.c") # => vhost is a.b.c
134
- # AMQ::Client::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/foo/bar") # => ArgumentError
135
- #
136
- #
137
- # @param [String] connection_string AMQP connection URI, à la JDBC connection string. For example: amqp://bus.megacorp.internal:5877.
138
- # @return [Hash] Connection parameters (:username, :password, :vhost, :host, :port, :ssl)
139
- #
140
- # @raise [ArgumentError] When connection URI schema is not amqp or amqps, or the path contains multiple segments
141
- #
142
- # @see http://bit.ly/ks8MXK Connecting to The Broker documentation guide
143
- # @api public
144
- def self.parse_amqp_url(connection_string)
145
- uri = URI.parse(connection_string)
146
- raise ArgumentError.new("Connection URI must use amqp or amqps schema (example: amqp://bus.megacorp.internal:5766), learn more at http://bit.ly/ks8MXK") unless %w{amqp amqps}.include?(uri.scheme)
147
-
148
- opts = {}
149
-
150
- opts[:scheme] = uri.scheme
151
- opts[:user] = URI.unescape(uri.user) if uri.user
152
- opts[:pass] = URI.unescape(uri.password) if uri.password
153
- opts[:host] = uri.host if uri.host
154
- opts[:port] = uri.port || AMQ::Client::Settings::AMQP_PORTS[uri.scheme]
155
- opts[:ssl] = uri.scheme == AMQ::Client::Settings::AMQPS
156
- if uri.path =~ %r{^/(.*)}
157
- raise ArgumentError.new("#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris") if $1.index('/')
158
- opts[:vhost] = URI.unescape($1)
159
- end
160
-
161
- opts
162
- end
163
- end
164
- end
165
- end
@@ -1,20 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Qrack
4
- # Channel ancestor class
5
- class Channel
6
-
7
- attr_accessor :number, :active, :frame_buffer
8
- attr_reader :client
9
-
10
- def initialize(client)
11
- @frame_buffer = []
12
- @client = client
13
- @number = client.channels.size
14
- @active = false
15
- client.channels[@number] = self
16
- end
17
-
18
- end
19
-
20
- end
@@ -1,247 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "qrack/amq-client-url"
4
-
5
- module Qrack
6
-
7
- class ClientTimeout < Timeout::Error; end
8
- class ConnectionTimeout < Timeout::Error; end
9
- class FrameTimeout < Timeout::Error; end
10
-
11
- # Client ancestor class
12
- class Client
13
-
14
- CONNECT_TIMEOUT = 5.0
15
- RETRY_DELAY = 10.0
16
-
17
- attr_reader :status, :host, :vhost, :port, :logging, :spec, :heartbeat, :last_method
18
- attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out, :connecting
19
-
20
-
21
- def initialize(connection_string_or_opts = Hash.new, opts = Hash.new)
22
- opts = case connection_string_or_opts
23
- when String then
24
- AMQ::Client::Settings.parse_amqp_url(connection_string_or_opts)
25
- when Hash then
26
- connection_string_or_opts
27
- else
28
- Hash.new
29
- end.merge(opts)
30
-
31
- @host = opts[:host] || 'localhost'
32
- @port = opts[:port] || (opts[:ssl] ? Qrack::Protocol::SSL_PORT : Qrack::Protocol::PORT)
33
- @user = opts[:user] || 'guest'
34
- @pass = opts[:pass] || 'guest'
35
- @vhost = opts[:vhost] || '/'
36
- @logfile = opts[:logfile] || nil
37
- @logging = opts[:logging] || false
38
- @ssl = opts[:ssl] || false
39
- @ssl_cert = opts[:ssl_cert] || nil
40
- @ssl_key = opts[:ssl_key] || nil
41
- @ssl_cert_string = opts[:ssl_cert_string] || nil
42
- @ssl_key_string = opts[:ssl_key_string] || nil
43
- @verify_ssl = opts[:verify_ssl].nil? || opts[:verify_ssl]
44
- @status = :not_connected
45
- @frame_max = opts[:frame_max] || 131072
46
- @channel_max = opts[:channel_max] || 0
47
- @heartbeat = opts[:heartbeat] || 0
48
- @connect_timeout = opts[:connect_timeout] || CONNECT_TIMEOUT
49
- @read_write_timeout = opts[:socket_timeout]
50
- @read_write_timeout = nil if @read_write_timeout == 0
51
- @disconnect_timeout = @read_write_timeout || @connect_timeout
52
- @logger = nil
53
- create_logger if @logging
54
- @message_in = false
55
- @message_out = false
56
- @last_method = nil
57
- @connecting = false
58
- @channels ||= []
59
- # Create channel 0
60
- @channel = create_channel()
61
- @exchanges ||= {}
62
- @queues ||= {}
63
- end
64
-
65
-
66
- # Closes all active communication channels and connection. If an error occurs a @Bunny::ProtocolError@ is raised. If successful, @Client.status@ is set to @:not_connected@.
67
-
68
- # @return [Symbol] @:not_connected@ if successful.
69
- def close
70
- return if @socket.nil? || @socket.closed?
71
-
72
- # Close all active channels
73
- channels.each do |c|
74
- Bunny::Timer::timeout(@disconnect_timeout) { c.close } if c.open?
75
- end
76
-
77
- # Close connection to AMQP server
78
- Bunny::Timer::timeout(@disconnect_timeout) { close_connection }
79
-
80
- rescue Exception
81
- # http://cheezburger.com/Asset/View/4033311488
82
- ensure
83
- # Clear the channels
84
- @channels = []
85
-
86
- # Create channel 0
87
- @channel = create_channel()
88
-
89
- # Close TCP Socket
90
- close_socket
91
- end
92
-
93
- alias stop close
94
-
95
- def connected?
96
- status == :connected
97
- end
98
-
99
- def connecting?
100
- connecting
101
- end
102
-
103
- def logging=(bool)
104
- @logging = bool
105
- create_logger if @logging
106
- end
107
-
108
- def next_payload(options = {})
109
- res = next_frame(options)
110
- res.payload if res
111
- end
112
-
113
- alias next_method next_payload
114
-
115
- def read(*args)
116
- send_command(:read, *args)
117
- # Got a SIGINT while waiting; give any traps a chance to run
118
- rescue Errno::EINTR
119
- retry
120
- end
121
-
122
- # Checks to see whether or not an undeliverable message has been returned as a result of a publish
123
- # with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
124
-
125
- # @param [Hash] opts Options.
126
- # @option opts [Numeric] :timeout (0.1) The method will wait for a return message until this timeout interval is reached.
127
- # @return [Hash] @{:header => nil, :payload => :no_return, :return_details => nil}@ if message is not returned before timeout. @{:header, :return_details, :payload}@ if message is returned. @:return_details@ is a hash @{:reply_code, :reply_text, :exchange, :routing_key}@.
128
- def returned_message(opts = {})
129
-
130
- begin
131
- frame = next_frame(:timeout => opts[:timeout] || 0.1)
132
- rescue Qrack::FrameTimeout
133
- return {:header => nil, :payload => :no_return, :return_details => nil}
134
- end
135
-
136
- method = frame.payload
137
- header = next_payload
138
-
139
- # If maximum frame size is smaller than message payload body then message
140
- # will have a message header and several message bodies
141
- msg = ''
142
- while msg.length < header.size
143
- msg << next_payload
144
- end
145
-
146
- # Return the message and related info
147
- {:header => header, :payload => msg, :return_details => method.arguments}
148
- end
149
-
150
- def switch_channel(chann)
151
- if (0...channels.size).include? chann
152
- @channel = channels[chann]
153
- chann
154
- else
155
- raise RuntimeError, "Invalid channel number - #{chann}"
156
- end
157
- end
158
-
159
- def write(*args)
160
- send_command(:write, *args)
161
- end
162
-
163
- def read_ready?(timeout, cancelator = nil)
164
- io = IO.select([ @socket, cancelator ].compact, nil, nil, timeout)
165
- io and io[0].include?(@socket)
166
- end
167
-
168
- private
169
-
170
- def close_socket(reason=nil)
171
- # Close the socket. The server is not considered dead.
172
- @socket.close if @socket and not @socket.closed?
173
- @socket = nil
174
- @status = :not_connected
175
- end
176
-
177
- def create_logger
178
- @logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
179
- @logger.level = Logger::INFO
180
- @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
181
- end
182
-
183
- def send_command(cmd, *args)
184
- begin
185
- raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
186
- if @read_write_timeout
187
- Bunny::Timer::timeout(@read_write_timeout, Qrack::ClientTimeout) do
188
- @socket.__send__(cmd, *args)
189
- end
190
- else
191
- @socket.__send__(cmd, *args)
192
- end
193
- rescue Errno::EPIPE, Errno::EAGAIN, Qrack::ClientTimeout, IOError => e
194
- # Ensure we close the socket when we are down to prevent further
195
- # attempts to write to a closed socket
196
- close_socket
197
- raise Bunny::ServerDownError, e.message
198
- end
199
- end
200
-
201
- def socket
202
- return @socket if @socket and (@status == :connected) and not @socket.closed?
203
-
204
- begin
205
- # Attempt to connect.
206
- @socket = Bunny::Timer::timeout(@connect_timeout, ConnectionTimeout) do
207
- TCPSocket.new(host, port)
208
- end
209
-
210
- if Socket.constants.include?('TCP_NODELAY') || Socket.constants.include?(:TCP_NODELAY)
211
- @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
212
- end
213
-
214
- if @ssl
215
- require 'openssl' unless defined? OpenSSL::SSL
216
- sslctx = OpenSSL::SSL::SSLContext.new
217
- initialize_client_pair(sslctx)
218
- @socket = OpenSSL::SSL::SSLSocket.new(@socket, sslctx)
219
- @socket.sync_close = true
220
- @socket.connect
221
- @socket.post_connection_check(host) if @verify_ssl
222
- @socket
223
- end
224
- rescue => e
225
- @status = :not_connected
226
- raise Bunny::ServerDownError, e.message
227
- end
228
-
229
- @socket
230
- end
231
-
232
- def initialize_client_pair(sslctx)
233
- if @ssl_cert
234
- @ssl_cert_string = File.read(@ssl_cert)
235
- end
236
- if @ssl_key
237
- @ssl_key_string = File.read(@ssl_key)
238
- end
239
-
240
- sslctx.cert = OpenSSL::X509::Certificate.new(@ssl_cert_string) if @ssl_cert_string
241
- sslctx.key = OpenSSL::PKey::RSA.new(@ssl_key_string) if @ssl_key_string
242
- sslctx
243
- end
244
-
245
- end
246
-
247
- end