qpid_proton 0.18.1 → 0.19.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/ext/cproton/cproton.c +863 -75
  3. data/lib/codec/data.rb +589 -815
  4. data/lib/codec/mapping.rb +142 -126
  5. data/lib/core/condition.rb +89 -0
  6. data/lib/core/connection.rb +188 -228
  7. data/lib/core/connection_driver.rb +202 -0
  8. data/lib/core/container.rb +366 -0
  9. data/lib/core/delivery.rb +76 -251
  10. data/lib/core/disposition.rb +21 -35
  11. data/lib/core/endpoint.rb +21 -53
  12. data/lib/core/event.rb +156 -0
  13. data/lib/core/exceptions.rb +109 -106
  14. data/lib/core/link.rb +24 -49
  15. data/lib/core/listener.rb +82 -0
  16. data/lib/core/message.rb +59 -155
  17. data/lib/core/messaging_handler.rb +190 -0
  18. data/lib/core/receiver.rb +38 -7
  19. data/lib/core/sasl.rb +43 -46
  20. data/lib/core/sender.rb +55 -32
  21. data/lib/core/session.rb +58 -58
  22. data/lib/core/ssl.rb +5 -13
  23. data/lib/core/ssl_details.rb +1 -2
  24. data/lib/core/ssl_domain.rb +5 -8
  25. data/lib/core/terminus.rb +62 -30
  26. data/lib/core/tracker.rb +45 -0
  27. data/lib/core/transfer.rb +121 -0
  28. data/lib/core/transport.rb +62 -97
  29. data/lib/core/uri.rb +73 -0
  30. data/lib/core/url.rb +11 -7
  31. data/lib/handler/adapter.rb +78 -0
  32. data/lib/handler/messaging_adapter.rb +127 -0
  33. data/lib/handler/messaging_handler.rb +128 -178
  34. data/lib/handler/reactor_messaging_adapter.rb +158 -0
  35. data/lib/messenger/messenger.rb +9 -8
  36. data/lib/messenger/subscription.rb +1 -2
  37. data/lib/messenger/tracker.rb +1 -2
  38. data/lib/messenger/tracker_status.rb +1 -2
  39. data/lib/qpid_proton.rb +36 -66
  40. data/lib/reactor/container.rb +40 -234
  41. data/lib/types/array.rb +73 -130
  42. data/lib/types/described.rb +2 -44
  43. data/lib/types/hash.rb +19 -56
  44. data/lib/types/strings.rb +1 -2
  45. data/lib/types/type.rb +68 -0
  46. data/lib/util/{handler.rb → deprecation.rb} +22 -15
  47. data/lib/util/error_handler.rb +4 -25
  48. data/lib/util/timeout.rb +1 -2
  49. data/lib/util/version.rb +1 -2
  50. data/lib/util/wrapper.rb +58 -38
  51. metadata +16 -33
  52. data/lib/core/base_handler.rb +0 -31
  53. data/lib/core/selectable.rb +0 -130
  54. data/lib/event/collector.rb +0 -148
  55. data/lib/event/event.rb +0 -318
  56. data/lib/event/event_base.rb +0 -91
  57. data/lib/event/event_type.rb +0 -71
  58. data/lib/handler/acking.rb +0 -70
  59. data/lib/handler/c_adaptor.rb +0 -47
  60. data/lib/handler/c_flow_controller.rb +0 -33
  61. data/lib/handler/endpoint_state_handler.rb +0 -217
  62. data/lib/handler/incoming_message_handler.rb +0 -74
  63. data/lib/handler/outgoing_message_handler.rb +0 -100
  64. data/lib/handler/wrapped_handler.rb +0 -76
  65. data/lib/reactor/acceptor.rb +0 -41
  66. data/lib/reactor/backoff.rb +0 -41
  67. data/lib/reactor/connector.rb +0 -115
  68. data/lib/reactor/global_overrides.rb +0 -44
  69. data/lib/reactor/link_option.rb +0 -90
  70. data/lib/reactor/reactor.rb +0 -196
  71. data/lib/reactor/session_per_connection.rb +0 -45
  72. data/lib/reactor/ssl_config.rb +0 -41
  73. data/lib/reactor/task.rb +0 -39
  74. data/lib/reactor/urls.rb +0 -45
  75. data/lib/util/class_wrapper.rb +0 -54
  76. data/lib/util/condition.rb +0 -47
  77. data/lib/util/constants.rb +0 -85
  78. data/lib/util/engine.rb +0 -82
  79. data/lib/util/reactor.rb +0 -32
  80. data/lib/util/swig_helper.rb +0 -114
  81. data/lib/util/uuid.rb +0 -32
@@ -0,0 +1,45 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ module Qpid::Proton
20
+
21
+ # Track the {Transfer::State} of a sent message.
22
+ class Tracker < Transfer
23
+ # @return [Sender] The parent {Sender} link.
24
+ def sender() link; end
25
+
26
+ # Re-delivery modifications sent by the receiver in {Delivery#release}
27
+ # @return [Hash] See the {Delivery#release} +opts+ parameter.
28
+ # @return [nil] If no modifications were requested by the receiver.
29
+ def modifications()
30
+ return nil if (state != MODIFIED)
31
+ d = Cproton.pn_delivery_remote(@impl)
32
+ {
33
+ :failed => Cproton.pn_disposition_is_failed(d),
34
+ :undeliverable => Cproton.pn_disposition_is_undeliverable(d),
35
+ :annotations => Codec::Data.to_object(Cproton.pn_disposition_annotations(d))
36
+ }
37
+ end
38
+
39
+ # Abort a partially-sent message.
40
+ # The tracker can no longer be used after calling {#abort}.
41
+ def abort()
42
+ Cproton.pn_delivery_abort(@impl)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,121 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ module Qpid::Proton
20
+
21
+ # Status of a message transfer on a {Link}
22
+ # Common base class for {Tracker} and {Delivery}.
23
+ class Transfer
24
+ include Util::Deprecation
25
+
26
+ # @!private
27
+ PROTON_METHOD_PREFIX = "pn_delivery"
28
+ # @!private
29
+ include Util::Wrapper
30
+
31
+ def self.wrap(impl)
32
+ return unless impl
33
+ self.fetch_instance(impl, :pn_delivery_attachments) ||
34
+ (Cproton.pn_link_is_sender(Cproton.pn_delivery_link(impl)) ? Tracker : Delivery).new(impl)
35
+ end
36
+
37
+ def initialize(impl)
38
+ @impl = impl
39
+ @inspect = nil
40
+ self.class.store_instance(self, :pn_delivery_attachments)
41
+ end
42
+
43
+ public
44
+
45
+ # AMQP Delivery States describing the outcome of a message transfer
46
+ module State
47
+ # Message was successfully processed by the receiver
48
+ ACCEPTED = Cproton::PN_ACCEPTED
49
+
50
+ # Message rejected as invalid and unprocessable by the receiver.
51
+ REJECTED = Cproton::PN_REJECTED
52
+
53
+ # Message was not (and will not be) processed by the receiver, but may be
54
+ # acceptable if re-delivered to another receiver
55
+ RELEASED = Cproton::PN_RELEASED
56
+
57
+ # Like {RELEASED}, but there are modifications (see {Tracker#modifications})
58
+ # that must be applied to the message by the {Sender} before re-delivering it.
59
+ MODIFIED = Cproton::PN_MODIFIED
60
+
61
+ # Partial message data received. Only used during link recovery.
62
+ RECEIVED = Cproton::PN_RECEIVED
63
+ end
64
+
65
+ include State
66
+
67
+ # @return [String] Unique ID for the transfer in the context of the {#link}
68
+ def id() Cproton.pn_delivery_tag(@impl); end
69
+
70
+ # @deprecated use {#id}
71
+ deprecated_alias :tag, :id
72
+
73
+ # @return [Boolean] True if the transfer has is remotely settled.
74
+ proton_caller :settled?
75
+
76
+ # @return [Integer] Remote state of the transfer, one of the values in {State}
77
+ def state() Cproton.pn_delivery_remote_state(@impl); end
78
+
79
+ # @return [Link] The parent link.
80
+ def link() Link.wrap(Cproton.pn_delivery_link(@impl)); end
81
+
82
+ # @return [Session] The parent session.
83
+ def session() link.session; end
84
+
85
+ # @return [Connection] The parent connection.
86
+ def connection() self.session.connection; end
87
+
88
+ # @return [Transport] The parent connection's transport.
89
+ def transport() self.connection.transport; end
90
+
91
+ # @deprecated internal use only
92
+ proton_caller :writable?
93
+ # @deprecated internal use only
94
+ proton_caller :readable?
95
+ # @deprecated internal use only
96
+ proton_caller :updated?
97
+ # @deprecated internal use only
98
+ proton_caller :clear
99
+ # @deprecated internal use only
100
+ proton_caller :pending
101
+ # @deprecated internal use only
102
+ proton_caller :partial?
103
+ # @deprecated internal use only
104
+ def update(state) Cproton.pn_delivery_update(@impl, state); end
105
+ # @deprecated internal use only
106
+ proton_caller :buffered?
107
+ # @deprecated internal use only
108
+ def local_state() Cproton.pn_delivery_local_state(@impl); end
109
+ # @deprecated use {#state}
110
+ deprecated_alias :remote_state, :state
111
+ # @deprecated internal use only
112
+ def settle(state = nil)
113
+ update(state) unless state.nil?
114
+ Cproton.pn_delivery_settle(@impl)
115
+ @inspect = inspect # Save the inspect string, the delivery pointer will go bad.
116
+ end
117
+
118
+ def inspect() @inspect || super; end
119
+ def to_s() inspect; end
120
+ end
121
+ end
@@ -1,4 +1,3 @@
1
- #--
2
1
  # Licensed to the Apache Software Foundation (ASF) under one
3
2
  # or more contributor license agreements. See the NOTICE file
4
3
  # distributed with this work for additional information
@@ -15,57 +14,18 @@
15
14
  # KIND, either express or implied. See the License for the
16
15
  # specific language governing permissions and limitations
17
16
  # under the License.
18
- #++
17
+
19
18
 
20
19
  module Qpid::Proton
21
20
 
22
- # A transport is used by a connection to interface with the network.
23
- #
24
- # A transport is associated with, at most, one Connection.
25
- #
26
- # == Client And Server Mode
27
- #
28
- # Initially, a transport is configured to be a client tranpsort. It can be
29
- # configured to act as a server when it is created.
30
- #
31
- # A client transport initiates outgoing connections.
32
- #
33
- # A client transport must be configured with the protocol layers to use and
34
- # cannot configure itself automatically.
35
- #
36
- # A server transport accepts incoming connections. It can automatically
37
- # configure itself to include the various protocol layers depending on the
38
- # incoming protocol headers.
39
- #
40
- # == Tracing Data
41
- #
42
- # Data can be traced into and out of the transport programmatically by setting
43
- # the #trace level to one of the defined trace values (TRACE_RAW, TRACE_FRM or
44
- # TRACE_DRV). Tracing can also be turned off programmatically by setting the
45
- # #trace level to TRACE_OFF.
46
- #
47
- # @example
48
- #
49
- # # turns on frame tracing
50
- # @transport.trace = Qpid::Proton::Transport::TRACE_FRM
51
- #
52
- # # ... do something where the frames are of interest, such as debugging
53
- #
54
- # # turn tracing off again
55
- # @transport.trace = Qpid::Proton::Transport::TRACE_NONE
56
- #
57
- # Tracing can also be enabled from the command line by defining the similarly
58
- # named environment variable before starting a Proton application:
59
- #
60
- # @example
61
- #
62
- # # enable tracing from the command line
63
- # PN_TRACE_FRM=1 ruby my_proton_app.rb
64
- #
21
+ # @deprecated all important features are available from {#Connection}
65
22
  class Transport
23
+ include Util::Deprecation
66
24
 
67
25
  # @private
68
- include Util::Engine
26
+ PROTON_METHOD_PREFIX = "pn_transport"
27
+ # @private
28
+ include Util::Wrapper
69
29
 
70
30
  # Turn logging off entirely.
71
31
  TRACE_OFF = Cproton::PN_TRACE_OFF
@@ -76,22 +36,13 @@ module Qpid::Proton
76
36
  # Log driver related events; i.e., initialization, end of stream, etc.
77
37
  TRACE_DRV = Cproton::PN_TRACE_DRV
78
38
 
79
- # @private
80
- CLIENT = 1
81
- # @private
82
- SERVER = 2
83
-
84
- # @private
85
- include Util::SwigHelper
86
-
87
- # @private
88
- PROTON_METHOD_PREFIX = "pn_transport"
39
+ proton_get :user
89
40
 
90
41
  # @!attribute channel_max
91
42
  #
92
43
  # @return [Integer] The maximum allowed channel.
93
44
  #
94
- proton_accessor :channel_max
45
+ proton_set_get :channel_max
95
46
 
96
47
  # @!attribute [r] remote_channel_max
97
48
  #
@@ -102,26 +53,34 @@ module Qpid::Proton
102
53
  # @!attribute max_frame_size
103
54
  #
104
55
  # @return [Integer] The maximum frame size.
105
- #
106
- proton_accessor :max_frame_size
56
+ proton_set_get :max_frame
57
+ proton_get :remote_max_frame
107
58
 
108
59
  # @!attribute [r] remote_max_frame_size
109
60
  #
110
61
  # @return [Integer] The maximum frame size of the transport's remote peer.
111
62
  #
112
- proton_reader :remote_max_frame_size
63
+ proton_get :remote_max_frame_size
113
64
 
114
65
  # @!attribute idle_timeout
115
66
  #
116
- # @return [Integer] The idle timeout.
67
+ # @deprecated use {Connection#open} with the +:idle_timeout+ option to set
68
+ # the timeout, and {Connection#idle_timeout} to query the remote timeout.
69
+ #
70
+ # The Connection timeout values are in *seconds* and are automatically
71
+ # converted.
72
+ #
73
+ # @return [Integer] The idle timeout in *milliseconds*.
117
74
  #
118
- proton_accessor :idle_timeout
75
+ proton_set_get :idle_timeout
119
76
 
120
- # @!attribute [r] remote_idle_timeout
77
+ # @!attribute [r] remote_idle_timeout in milliseconds
78
+ #
79
+ # @deprecated Use {Connection#idle_timeout} to query the remote timeout.
121
80
  #
122
81
  # @return [Integer] The idle timeout for the transport's remote peer.
123
82
  #
124
- proton_accessor :remote_idle_timeout
83
+ proton_set_get :remote_idle_timeout
125
84
 
126
85
  # @!attribute [r] capacity
127
86
  #
@@ -190,49 +149,34 @@ module Qpid::Proton
190
149
  #
191
150
  # @return [Integer] The number of frames output by a transport.
192
151
  #
193
- proton_reader :frames_output
152
+ proton_get :frames_output
194
153
 
195
154
  # @!attribute [r] frames_input
196
155
  #
197
156
  # @return [Integer] The number of frames input by a transport.
198
157
  #
199
- proton_reader :frames_input
158
+ proton_get :frames_input
200
159
 
201
160
  # @private
202
161
  include Util::ErrorHandler
203
162
 
204
- can_raise_error :process, :error_class => TransportError
205
- can_raise_error :close_tail, :error_class => TransportError
206
- can_raise_error :pending, :error_class => TransportError, :below => Error::EOS
207
- can_raise_error :close_head, :error_class => TransportError
208
-
209
- # @private
210
- include Util::Wrapper
211
-
212
163
  # @private
213
164
  def self.wrap(impl)
214
165
  return nil if impl.nil?
215
166
 
216
- self.fetch_instance(impl, :pn_transport_attachments) || Transport.new(nil, impl)
167
+ self.fetch_instance(impl, :pn_transport_attachments) || Transport.new(impl)
217
168
  end
218
169
 
219
170
  # Creates a new transport instance.
220
- #
221
- # @param mode [Integer] The transport mode, either CLIENT or SERVER
222
- # @param impl [pn_transport_t] Should not be used.
223
- #
224
- # @raise [TransportError] If the mode is invalid.
225
- #
226
- def initialize(mode = nil, impl = Cproton.pn_transport)
171
+ def initialize(impl = Cproton.pn_transport)
227
172
  @impl = impl
228
- if mode == SERVER
229
- Cproton.pn_transport_set_server(@impl)
230
- elsif (!mode.nil? && mode != CLIENT)
231
- raise TransportError.new("cannot create transport for mode: #{mode}")
232
- end
233
173
  self.class.store_instance(self, :pn_transport_attachments)
234
174
  end
235
175
 
176
+ # Set server mode for this tranport - enables protocol detection
177
+ # and server-side authentication for incoming connections
178
+ def set_server() Cproton.pn_transport_set_server(@impl); end
179
+
236
180
  # Returns whether the transport has any buffered data.
237
181
  #
238
182
  # @return [Boolean] True if the transport has no buffered data.
@@ -241,15 +185,15 @@ module Qpid::Proton
241
185
  Cproton.pn_transport_quiesced(@impl)
242
186
  end
243
187
 
244
- # Returns additional information about the condition of the transport.
245
- #
246
- # When a TRANSPORT_ERROR event occurs, this operaiton can be used to
247
- # access the details of the error condition.
248
- #
249
- # The object returned is valid until the Transport is discarded.
250
- #
188
+ # @return [Condition, nil] transport error condition or nil if there is no error.
251
189
  def condition
252
- condition_to_object Cproton.pn_transport_condition(@impl)
190
+ Condition.convert(Cproton.pn_transport_condition(@impl))
191
+ end
192
+
193
+ # Set the error condition for the transport.
194
+ # @param c [Condition] The condition to set
195
+ def condition=(c)
196
+ Condition.assign(Cproton.pn_transport_condition(@impl), c)
253
197
  end
254
198
 
255
199
  # Binds to the given connection.
@@ -400,7 +344,7 @@ module Qpid::Proton
400
344
  # @return [SSL] The SSL object.
401
345
  #
402
346
  def ssl(domain = nil, session_details = nil)
403
- @ssl ||= SSL.create(self, domain, session_details) if @ssl.nil?
347
+ @ssl ||= SSL.create(self, domain, session_details)
404
348
  end
405
349
 
406
350
  # @private
@@ -408,6 +352,27 @@ module Qpid::Proton
408
352
  !@ssl.nil?
409
353
  end
410
354
 
411
- end
355
+ # @private
356
+ # Options are documented {Connection#open}, keep that consistent with this
357
+ def apply opts
358
+ sasl if opts[:sasl_enabled] # Explicitly enabled
359
+ unless opts.include?(:sasl_enabled) && !opts[:sasl_enabled] # Not explicitly disabled
360
+ sasl.allowed_mechs = opts[:sasl_allowed_mechs] if opts.include? :sasl_allowed_mechs
361
+ sasl.allow_insecure_mechs = opts[:sasl_allow_insecure_mechs] if opts.include? :sasl_allow_insecure_mechs
362
+ end
363
+ self.channel_max= opts[:max_sessions] if opts.include? :max_sessions
364
+ self.max_frame = opts[:max_frame_size] if opts.include? :max_frame_size
365
+ # NOTE: The idle_timeout option is in Numeric *seconds*, can be Integer, Float or Rational.
366
+ # This is consistent with idiomatic ruby.
367
+ # The transport #idle_timeout property is in *milliseconds* passed direct to C.
368
+ # Direct use of the transport is deprecated.
369
+ self.idle_timeout= (opts[:idle_timeout]*1000).round if opts.include? :idle_timeout
370
+ self.ssl(opts[:ssl_domain]) if opts[:ssl_domain]
371
+ end
412
372
 
373
+ can_raise_error :process, :error_class => TransportError
374
+ can_raise_error :close_tail, :error_class => TransportError
375
+ can_raise_error :pending, :error_class => TransportError, :below => Error::EOS
376
+ can_raise_error :close_head, :error_class => TransportError
377
+ end
413
378
  end
data/lib/core/uri.rb ADDED
@@ -0,0 +1,73 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+
19
+ require 'uri'
20
+
21
+ # Extend the standard ruby {URI} with AMQP and AMQPS schemes
22
+ module URI
23
+ # AMQP URI scheme for the AMQP protocol
24
+ class AMQP < Generic
25
+ DEFAULT_PORT = 5672
26
+
27
+ # @return [String] The AMQP address is the {#path} stripped of any leading "/"
28
+ def amqp_address() path[0] == "/" ? path[1..-1] : path; end
29
+ end
30
+ @@schemes['AMQP'] = AMQP
31
+
32
+ # AMQPS URI scheme for the AMQP protocol over TLS
33
+ class AMQPS < AMQP
34
+ DEFAULT_PORT = 5671
35
+ end
36
+ @@schemes['AMQPS'] = AMQPS
37
+ end
38
+
39
+ module Qpid::Proton
40
+ # Returns +s+ converted to a {URI::AMQP} or {URI::AMQPS} object
41
+ #
42
+ # Shortcut strings are allowed: an "amqp://" prefix is added if +s+ does
43
+ # not already look like an 'amqp:', 'amqps:' URI.
44
+ #
45
+ # @note this does not give the same result as a standard URI parser in all cases.
46
+ # For standard conversion to a URI use: {#URI}(s)
47
+ #
48
+ # @param s [String,URI] String to convert to a URI, or a URI object.
49
+ # A URI object with no scheme will be converted to {URI::AMQP}
50
+ # @return [URI::AMQP] A valid {URI::AMQP} or {URI::AMQPS} object
51
+ # @raise [BadURIError] s is a URI object with a non-AMQP scheme
52
+ # @raise [InvalidURIError] s cannot be parsed as a URI or shortcut
53
+ # @raise [::ArgumentError] s is not a string or URI
54
+ #
55
+ def self.uri(s)
56
+ case s
57
+ when URI::AMQP then s # Pass-thru
58
+ when URI::Generic
59
+ s.scheme ||= 'amqp'
60
+ u = URI.parse(s.to_s) # Re-parse as amqp
61
+ raise URI::BadURIError, "Not an AMQP URI: '#{u}'" unless u.is_a? URI::AMQP
62
+ u
63
+ else
64
+ s = String.try_convert s
65
+ raise ::ArgumentError, "bad argument (expected URI object or URI string)" unless s
66
+ case s
67
+ when %r{^amqps?:} then URI.parse(s) # Looks like an AMQP URI
68
+ when %r{^//} then URI.parse("amqp:#{s}") # Looks like a scheme-less URI
69
+ else URI.parse("amqp://#{s}") # Treat as a bare host:port/path string
70
+ end
71
+ end
72
+ end
73
+ end