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
data/lib/codec/mapping.rb CHANGED
@@ -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,155 +14,172 @@
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
- #++
19
17
 
20
- module Qpid::Proton::Codec
21
18
 
22
- # Maps between Proton types and their Ruby native language counterparts.
23
- #
24
- # @private
25
- class Mapping
19
+ module Qpid::Proton
20
+ module Codec
26
21
 
27
- attr_reader :code
28
- attr_reader :put_method
29
- attr_reader :get_method
30
-
31
- # Creates a new mapping.
32
- #
33
- # ==== Arguments
22
+ # Maps between Proton types and their Ruby native language counterparts.
34
23
  #
35
- # * code - the AMQP code for this type
36
- # * name - the AMQP name for this type
37
- # * klasses - native Ruby classes that are mapped to this AMQP type
38
- # * getter - overrides the get method for the type
39
- def initialize(code, name, klasses = nil, getter = nil)
40
-
41
- @debug = (name == "bool")
42
-
43
- @code = code
44
- @name = name
45
-
46
- @@by_preferred ||= {}
47
- @@by_code ||= {}
48
- @@by_code["#{code}"] = self
49
- @@by_name ||= {}
50
- @@by_name[name] = self
51
- @@by_class ||= {}
52
-
53
- unless klasses.nil?
54
- klasses.each do |klass|
55
- raise "entry exists for #{klass}" if @@by_class.keys.include? klass
56
- @@by_class[klass] = self unless klass.nil?
24
+ # @private
25
+ class Mapping
26
+
27
+ attr_reader :code
28
+ attr_reader :put_method
29
+ attr_reader :get_method
30
+
31
+ @@by_code = {}
32
+ @@by_class = {}
33
+
34
+ # Creates a new mapping.
35
+ #
36
+ # ==== Arguments
37
+ #
38
+ # * code - the AMQP code for this type
39
+ # * name - the AMQP name for this type
40
+ # * klasses - native Ruby classes that are mapped to this AMQP type
41
+ # * getter - overrides the get method for the type
42
+ def initialize(code, name, klasses = nil, getter = nil)
43
+
44
+ @code = code
45
+ @name = name
46
+
47
+ @@by_code[code] = self
48
+
49
+ unless klasses.nil?
50
+ klasses.each do |klass|
51
+ raise "entry exists for #{klass}" if @@by_class.keys.include? klass
52
+ @@by_class[klass] = self unless klass.nil?
53
+ end
57
54
  end
58
- end
59
55
 
60
- @put_method = (name + "=").intern
56
+ @put_method = (name + "=").intern
61
57
 
62
- if getter.nil?
63
- @get_method = name.intern
64
- else
65
- @get_method = getter.intern
58
+ if getter.nil?
59
+ @get_method = name.intern
60
+ else
61
+ @get_method = getter.intern
62
+ end
66
63
  end
67
- end
68
-
69
- def to_s; @name; end
70
64
 
71
- def put(data, value)
72
- data.__send__(@put_method, value)
73
- end
65
+ def to_s; @name; end
74
66
 
75
- def get(data)
76
- data.__send__(@get_method)
77
- end
67
+ def put(data, value)
68
+ data.__send__(@put_method, value)
69
+ end
78
70
 
79
- def self.for_class(klass) # :nodoc:
80
- klass and (@@by_class[klass] or self.for_class(klass.superclass))
81
- end
71
+ def get(data)
72
+ data.__send__(@get_method)
73
+ end
82
74
 
83
- def self.for_code(code)
84
- @@by_code["#{code}"]
85
- end
75
+ def self.for_class(klass)
76
+ c = klass
77
+ c = c.superclass while c && (x = @@by_class[c]).nil?
78
+ raise TypeError, "#{klass} cannot be converted to AMQP" unless x
79
+ x
80
+ end
86
81
 
87
- end
82
+ def self.for_code(code)
83
+ @@by_code[code]
84
+ end
88
85
 
89
- NULL = Mapping.new(Cproton::PN_NULL, "null", [NilClass], "nil?")
90
- BOOL = Mapping.new(Cproton::PN_BOOL, "bool", [TrueClass, FalseClass], "bool")
91
- UBYTE = Mapping.new(Cproton::PN_UBYTE, "ubyte")
92
- BYTE = Mapping.new(Cproton::PN_BYTE, "byte")
93
- USHORT = Mapping.new(Cproton::PN_USHORT, "ushort")
94
- SHORT = Mapping.new(Cproton::PN_SHORT, "short")
95
- UINT = Mapping.new(Cproton::PN_UINT, "uint")
96
- INT = Mapping.new(Cproton::PN_INT, "int")
97
- CHAR = Mapping.new(Cproton::PN_CHAR, "char")
98
- ULONG = Mapping.new(Cproton::PN_ULONG, "ulong")
99
- LONG = Mapping.new(Cproton::PN_LONG, "long", [Integer])
100
- TIMESTAMP = Mapping.new(Cproton::PN_TIMESTAMP, "timestamp", [Date, Time])
101
- FLOAT = Mapping.new(Cproton::PN_FLOAT, "float")
102
- DOUBLE = Mapping.new(Cproton::PN_DOUBLE, "double", [Float])
103
- DECIMAL32 = Mapping.new(Cproton::PN_DECIMAL32, "decimal32")
104
- DECIMAL64 = Mapping.new(Cproton::PN_DECIMAL64, "decimal64")
105
- DECIMAL128 = Mapping.new(Cproton::PN_DECIMAL128, "decimal128")
106
- UUID = Mapping.new(Cproton::PN_UUID, "uuid")
107
- BINARY = Mapping.new(Cproton::PN_BINARY, "binary")
108
- STRING = Mapping.new(Cproton::PN_STRING, "string", [String, Symbol,
109
- Qpid::Proton::Types::UTFString,
110
- Qpid::Proton::Types::BinaryString])
111
-
112
- # @private
113
- class << STRING
114
- def put(data, value)
115
- # if we have a symbol then convert it to a string
116
- value = value.to_s if value.is_a?(Symbol)
117
-
118
- isutf = false
119
-
120
- if value.is_a?(Qpid::Proton::Types::UTFString)
121
- isutf = true
122
- else
123
- # For Ruby 1.8 we will just treat all strings as binary.
124
- # For Ruby 1.9+ we can check the encoding first to see what it is
125
- if RUBY_VERSION >= "1.9"
126
- # If the string is ASCII-8BIT then treat is as binary. Otherwise,
127
- # try to convert it to UTF-8 and, if successful, send as that.
128
- if value.encoding != Encoding::ASCII_8BIT &&
129
- value.encode(Encoding::UTF_8).valid_encoding?
130
- isutf = true
131
- end
86
+ # Convert x to a Mapping
87
+ def self.[](x)
88
+ case x
89
+ when Mapping then x
90
+ when Integer then @@by_code[x]
91
+ when Types::Type then @@by_code[x.code]
132
92
  end
133
93
  end
134
94
 
135
- data.string = value if isutf
136
- data.binary = value if !isutf
137
-
138
95
  end
139
- end
140
96
 
141
- SYMBOL = Mapping.new(Cproton::PN_SYMBOL, "symbol")
142
- DESCRIBED = Mapping.new(Cproton::PN_DESCRIBED, "described", [Qpid::Proton::Types::Described], "get_described")
143
- ARRAY = Mapping.new(Cproton::PN_ARRAY, "array", nil, "get_array")
144
- LIST = Mapping.new(Cproton::PN_LIST, "list", [::Array], "get_array")
145
- MAP = Mapping.new(Cproton::PN_MAP, "map", [::Hash], "get_map")
146
-
147
- # @private
148
- class << MAP
149
- def put(data, map, options = {})
150
- data.put_map
151
- data.enter
152
- map.each_pair do |key, value|
153
- if options[:keys] == :SYMBOL
154
- SYMBOL.put(data, key)
97
+ NULL = Mapping.new(Cproton::PN_NULL, "null", [NilClass])
98
+ BOOL = Mapping.new(Cproton::PN_BOOL, "bool", [TrueClass, FalseClass])
99
+ UBYTE = Mapping.new(Cproton::PN_UBYTE, "ubyte")
100
+ BYTE = Mapping.new(Cproton::PN_BYTE, "byte")
101
+ USHORT = Mapping.new(Cproton::PN_USHORT, "ushort")
102
+ SHORT = Mapping.new(Cproton::PN_SHORT, "short")
103
+ UINT = Mapping.new(Cproton::PN_UINT, "uint")
104
+ INT = Mapping.new(Cproton::PN_INT, "int")
105
+ CHAR = Mapping.new(Cproton::PN_CHAR, "char")
106
+ ULONG = Mapping.new(Cproton::PN_ULONG, "ulong")
107
+ LONG = Mapping.new(Cproton::PN_LONG, "long", [Integer])
108
+ TIMESTAMP = Mapping.new(Cproton::PN_TIMESTAMP, "timestamp", [Date, Time])
109
+ FLOAT = Mapping.new(Cproton::PN_FLOAT, "float")
110
+ DOUBLE = Mapping.new(Cproton::PN_DOUBLE, "double", [Float])
111
+ DECIMAL32 = Mapping.new(Cproton::PN_DECIMAL32, "decimal32")
112
+ DECIMAL64 = Mapping.new(Cproton::PN_DECIMAL64, "decimal64")
113
+ DECIMAL128 = Mapping.new(Cproton::PN_DECIMAL128, "decimal128")
114
+ UUID = Mapping.new(Cproton::PN_UUID, "uuid")
115
+ BINARY = Mapping.new(Cproton::PN_BINARY, "binary")
116
+ STRING = Mapping.new(Cproton::PN_STRING, "string", [::String,
117
+ Types::UTFString,
118
+ Types::BinaryString])
119
+ SYMBOL = Mapping.new(Cproton::PN_SYMBOL, "symbol", [::Symbol])
120
+ DESCRIBED = Mapping.new(Cproton::PN_DESCRIBED, "described", [Types::Described])
121
+ ARRAY = Mapping.new(Cproton::PN_ARRAY, "array", [Types::UniformArray])
122
+ LIST = Mapping.new(Cproton::PN_LIST, "list", [::Array])
123
+ MAP = Mapping.new(Cproton::PN_MAP, "map", [::Hash])
124
+
125
+ private
126
+
127
+ class << STRING
128
+ def put(data, value)
129
+ # if we have a symbol then convert it to a string
130
+ value = value.to_s if value.is_a?(Symbol)
131
+
132
+ isutf = false
133
+
134
+ if value.is_a?(Types::UTFString)
135
+ isutf = true
155
136
  else
156
- Mapping.for_class(key.class).put(data, key)
137
+ # For Ruby 1.8 we will just treat all strings as binary.
138
+ # For Ruby 1.9+ we can check the encoding first to see what it is
139
+ if RUBY_VERSION >= "1.9"
140
+ # If the string is ASCII-8BIT then treat is as binary. Otherwise,
141
+ # try to convert it to UTF-8 and, if successful, send as that.
142
+ if value.encoding != Encoding::ASCII_8BIT &&
143
+ value.encode(Encoding::UTF_8).valid_encoding?
144
+ isutf = true
145
+ end
146
+ end
157
147
  end
158
148
 
159
- if value.nil?
160
- data.null
161
- else
162
- Mapping.for_class(value.class).put(data, value)
149
+ data.string = value if isutf
150
+ data.binary = value if !isutf
151
+ end
152
+ end
153
+
154
+ class << MAP
155
+ def put(data, map, options = {})
156
+ data.put_map
157
+ data.enter
158
+ map.each_pair do |key, value|
159
+ if options[:keys] == :SYMBOL
160
+ SYMBOL.put(data, key)
161
+ else
162
+ data.object = key
163
+ end
164
+
165
+ if value.nil?
166
+ data.null
167
+ else
168
+ data.object = value
169
+ end
163
170
  end
171
+ data.exit
164
172
  end
165
- data.exit
166
173
  end
167
- end
168
174
 
175
+ class << DESCRIBED
176
+ def put(data, described)
177
+ data.put_described
178
+ data.enter
179
+ data.object = described.descriptor
180
+ data.object = described.value
181
+ data.exit
182
+ end
183
+ end
184
+ end
169
185
  end
@@ -0,0 +1,89 @@
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
+ # An AMQP error condition.
22
+ #
23
+ # An error sent across an AMQP connection has a name, description and optional extra info.
24
+ # The {Connectin}, {Session} and {Link} endpoint classes all have a #condition method to
25
+ # check for errors.
26
+ #
27
+ # {Condition} can also be raised as an exception.
28
+ #
29
+ class Condition < ProtonError
30
+
31
+ attr_reader :name, :description, :info
32
+
33
+ def initialize(name, description = nil, info = nil)
34
+ @name = name
35
+ @description = description
36
+ @info = info
37
+ super(to_s)
38
+ end
39
+
40
+ def to_s() "#{@name}: #{@description}"; end
41
+
42
+ def inspect() "#{self.class.name}(#{@name.inspect}, #{@description.inspect}, #{@info.inspect})"; end
43
+
44
+ def ==(other)
45
+ ((other.is_a? Condition) &&
46
+ (other.name == self.name) &&
47
+ (other.description == self.description) &&
48
+ (other.info == self.info))
49
+ end
50
+
51
+ # Convert an object to a condition.
52
+ # @param obj the object to turn into a condition
53
+ # @param default_name name to use if obj does not imply a name
54
+ # @return [Condition] Conversion depends on the type of obj
55
+ # - Condition: return obj
56
+ # - Exception: return Condition(obj.class.name, obj.to_s)
57
+ # - String-like: return String.try_convert(obj)
58
+ # - nil: return nil
59
+ # @raise ::ArgumentError if obj is not convertible to {Condition}
60
+ def self.convert(obj, default_name="error")
61
+ case obj
62
+ when nil then nil
63
+ when Condition then obj
64
+ when Exception then Condition.new(obj.class.name, obj.to_s)
65
+ when SWIG::TYPE_p_pn_condition_t
66
+ if Cproton.pn_condition_is_set(obj)
67
+ Condition.new(Cproton.pn_condition_get_name(obj),
68
+ Cproton.pn_condition_get_description(obj),
69
+ Codec::Data.to_object(Cproton.pn_condition_info(obj)))
70
+ end
71
+ else
72
+ raise ::ArgumentError, "can't convert #{obj.class.name} to #{self.class.name}" unless obj.respond_to? :to_str
73
+ Condition.new(default_name, obj.to_str)
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def self.assign(impl, cond)
80
+ Cproton.pn_condition_clear(impl)
81
+ if cond
82
+ cond = self.convert(cond)
83
+ Cproton.pn_condition_set_name(impl, cond.name) if cond.name
84
+ Cproton.pn_condition_set_description(impl, cond.description) if cond.description
85
+ Codec::Data.from_object(Cproton.pn_condition_info(impl), cond.info) if cond.info
86
+ end
87
+ end
88
+ end
89
+ 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,214 +14,167 @@
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 Connection has at most one Qpid::Proton::Transport instance.
23
- #
21
+ # An AMQP connection.
24
22
  class Connection < Endpoint
25
-
26
- # @private
27
- include Util::SwigHelper
28
-
29
- # @private
30
23
  PROTON_METHOD_PREFIX = "pn_connection"
31
-
32
- # @!attribute hostname
33
- #
34
- # @return [String] The AMQP hostname for the connection.
35
- #
36
- proton_accessor :hostname
37
-
38
- # @!attribute user
39
- # The user name for authentication.
40
- #
41
- # @return [String] the user name
42
- proton_accessor :user
43
-
44
- # @private
45
- proton_writer :password
46
-
47
- # @private
48
- proton_reader :attachments
49
-
50
- attr_accessor :overrides
51
- attr_accessor :session_policy
52
-
53
- # @private
54
24
  include Util::Wrapper
25
+ include Util::Deprecation
55
26
 
56
27
  # @private
57
28
  def self.wrap(impl)
58
29
  return nil if impl.nil?
59
-
60
30
  self.fetch_instance(impl, :pn_connection_attachments) || Connection.new(impl)
61
31
  end
62
32
 
63
- # Constructs a new instance of Connection.
64
- #
65
- # You do *not* need to provide the underlying C struct, as this is
66
- # automatically generated as needed. The argument is a convenience
67
- # for returning existing Connection objects.
68
- #
69
- # @param impl [pn_connection_t] The pn_connection_t struct.
70
- #
33
+ # @private
71
34
  def initialize(impl = Cproton.pn_connection)
72
35
  super()
73
36
  @impl = impl
74
- @offered_capabilities = nil
75
- @desired_capabilities = nil
76
- @properties = nil
77
37
  @overrides = nil
78
- @collector = nil
79
38
  @session_policy = nil
39
+ @link_count = 0
40
+ @link_prefix = ""
80
41
  self.class.store_instance(self, :pn_connection_attachments)
81
42
  end
82
43
 
83
- def overrides?
84
- !@overrides.nil?
85
- end
44
+ # @return [String] The AMQP hostname for the connection.
45
+ def virtual_host() Cproton.pn_connection_remote_hostname(@impl); end
46
+ deprecated_alias :remote_hostname, :virtual_host
86
47
 
87
- def session_policy?
88
- !@session_policy.nil?
89
- end
48
+ # @!attribute hostname
49
+ # @deprecated use {#virtual_host}
50
+ proton_set_get :hostname
90
51
 
91
- # This method is used when working within the context of an event.
92
- #
93
- # @return [Connection] The connection itself.
94
- #
95
- def connection
96
- self
52
+ # @return [String] User name used for authentication (outgoing connection)
53
+ # or the authenticated user name (incoming connection)
54
+ def user()
55
+ Cproton.pn_connection_get_user(impl) or (connection.transport && connection.transport.user)
97
56
  end
98
57
 
99
- # The Transport to which this connection is bound.
100
- #
101
- # @return [Transport] The transport, or nil if the Connection is unbound.
102
- #
103
- def transport
104
- Transport.wrap(Cproton.pn_connection_transport(@impl))
105
- end
58
+ # @deprecated no replacement
59
+ def overrides?() deprecated __method__; false; end
106
60
 
107
- # Associates the connection with an event collector.
108
- #
109
- # By doing this, key changes in the endpoint's state are reported to
110
- # the connector via Event objects that can be inspected and processed.
111
- #
112
- # Note that, by registering a collector, the user is requesting that an
113
- # indefinite number of events be queued up on its behalf. This means
114
- # that, unless the application eventual processes these events, the
115
- # storage requirements for keeping them will grow without bound. So be
116
- # careful and do not register a collector with a connection unless the
117
- # application will process the events.
118
- #
119
- # @param collector [Event::Collector] The event collector.
120
- #
121
- def collect(collector)
122
- if collector.nil?
123
- Cproton.pn_connection_collect(@impl, nil)
124
- else
125
- Cproton.pn_connection_collect(@impl, collector.impl)
126
- end
127
- @collector = collector
128
- end
61
+ # @deprecated no replacement
62
+ def session_policy?() deprecated __method__; false; end
129
63
 
130
- # Get the AMQP container name advertised by the remote connection
131
- # endpoint.
132
- #
133
- # This will return nil until the REMOTE_ACTIVE state is reached.
134
- #
135
- # Any non-nil container returned by this operation will be valid
136
- # until the connection is unbound from a transport, or freed,
137
- # whichever happens sooner.
138
- #
139
- # @return [String] The remote connection's AMQP container name.
140
- #
141
- # @see #container
142
- #
143
- def remote_container
144
- Cproton.pn_connection_remote_container(@impl)
64
+ # @return [Connection] self
65
+ def connection() self; end
66
+
67
+ # @return [Transport, nil] transport bound to this connection, or nil if unbound.
68
+ def transport() Transport.wrap(Cproton.pn_connection_transport(@impl)); end
69
+
70
+ # @return AMQP container ID advertised by the remote peer.
71
+ # To get the local container ID use {#container} and {Container#id}
72
+ def container_id() Cproton.pn_connection_remote_container(@impl); end
73
+ deprecated_alias :remote_container, :container_id
74
+
75
+ # @return [Container] the container managing this connection
76
+ attr_reader :container
77
+
78
+ # @return [Array<Symbol>] offered capabilities provided by the remote peer
79
+ def offered_capabilities
80
+ Codec::Data.to_object(Cproton.pn_connection_remote_offered_capabilities(@impl))
145
81
  end
82
+ deprecated_alias :remote_offered_capabilities, :offered_capabilities
146
83
 
147
- def container=(name)
148
- Cproton.pn_connection_set_container(@impl, name)
84
+ # @return [Array<Symbol>] desired capabilities provided by the remote peer
85
+ def desired_capabilities
86
+ Codec::Data.to_object(Cproton.pn_connection_remote_desired_capabilities(@impl))
149
87
  end
88
+ deprecated_alias :remote_desired_capabilities, :desired_capabilities
150
89
 
151
- def container
152
- Cproton.pn_connection_get_container(@impl)
90
+ # @return [Hash] connection-properties provided by the remote peer
91
+ def properties
92
+ Codec::Data.to_object(Cproton.pn_connection_remote_properties(@impl))
153
93
  end
94
+ deprecated_alias :remote_properties, :properties
154
95
 
155
- # Get the AMQP hostname set by the remote connection endpoint.
96
+ # Open the local end of the connection.
156
97
  #
157
- # This will return nil until the #REMOTE_ACTIVE state is
158
- # reached.
98
+ # @option opts [MessagingHandler] :handler handler for events related to this connection.
159
99
  #
160
- # @return [String] The remote connection's AMQP hostname.
100
+ # @option opts [String] :user User name for authentication
101
+ # @option opts [String] :password Authentication secret
102
+ # @option opts [String] :virtual_host Virtual host name
103
+ # @option opts [String] :container_id (provided by {Container}) override advertised container-id
161
104
  #
162
- # @see #hostname
105
+ # @option opts [Hash<Symbol=>Object>] :properties Application-defined properties
106
+ # @option opts [Array<Symbol>] :offered_capabilities Extensions the endpoint supports
107
+ # @option opts [Array<Symbol>] :desired_capabilities Extensions the endpoint can use
163
108
  #
164
- def remote_hostname
165
- Cproton.pn_connection_remote_hostname(@impl)
166
- end
167
-
168
- # Get the AMQP offered capabilities suppolied by the remote connection
169
- # endpoint.
109
+ # @option opts [Numeric] :idle_timeout Seconds before closing an idle connection
110
+ # @option opts [Integer] :max_sessions Limit the number of active sessions
111
+ # @option opts [Integer] :max_frame_size Limit the size of AMQP frames
170
112
  #
171
- # This object returned is valid until the connection is freed. The Data
172
- # object will be empty until the remote connection is opened, as
173
- # indicated by the #REMOTE_ACTIVE flag.
113
+ # @option opts [Boolean] :sasl_enabled (false) Enable or disable SASL.
114
+ # @option opts [Boolean] :sasl_allow_insecure_mechs (false) Allow mechanisms send secrets in clear text
115
+ # @option opts [String] :sasl_allowed_mechs SASL mechanisms allowed by this end of the connection
174
116
  #
175
- # @return [Data] The offered capabilities.
117
+ # @option opts [SSLDomain] :ssl_domain SSL configuration domain.
176
118
  #
177
- def remote_offered_capabilities
178
- data_to_object(Cproton.pn_connection_remote_offered_capabilities(@impl))
119
+ def open(opts=nil)
120
+ return if local_active?
121
+ apply opts if opts
122
+ Cproton.pn_connection_open(@impl)
179
123
  end
180
124
 
181
- # Get the AMQP desired capabilities supplied by the remote connection
182
- # endpoint.
183
- #
184
- # The object returned is valid until the connection is freed. The Data
185
- # object will be empty until the remote connection is opened, as
186
- # indicated by the #REMOTE_ACTIVE flag.
187
- #
188
- # @return [Data] The desired capabilities.
189
- #
190
- def remote_desired_capabilities
191
- data_to_object(Cproton.pn_connection_remote_desired_capabilities(@impl))
125
+ # @private
126
+ def apply opts
127
+ # NOTE: Only connection options are set here. Transport options are set
128
+ # with {Transport#apply} from the connection_driver (or in
129
+ # on_connection_bound if not using a connection_driver)
130
+ @container = opts[:container]
131
+ cid = opts[:container_id] || (@container && @container.id) || SecureRandom.uuid
132
+ cid = cid.to_s if cid.is_a? Symbol # Allow symbols as container name
133
+ Cproton.pn_connection_set_container(@impl, cid)
134
+ Cproton.pn_connection_set_user(@impl, opts[:user]) if opts[:user]
135
+ Cproton.pn_connection_set_password(@impl, opts[:password]) if opts[:password]
136
+ Cproton.pn_connection_set_hostname(@impl, opts[:virtual_host]) if opts[:virtual_host]
137
+ @link_prefix = opts[:link_prefix] || cid
138
+ Codec::Data.from_object(Cproton.pn_connection_offered_capabilities(@impl),
139
+ Types.symbol_array(opts[:offered_capabilities]))
140
+ Codec::Data.from_object(Cproton.pn_connection_desired_capabilities(@impl),
141
+ Types.symbol_array(opts[:desired_capabilities]))
142
+ Codec::Data.from_object(Cproton.pn_connection_properties(@impl),
143
+ Types.symbol_keys(opts[:properties]))
192
144
  end
193
145
 
194
- # Get the AMQP connection properties supplie by the remote connection
195
- # endpoint.
196
- #
197
- # The object returned is valid until the connection is freed. The Data
198
- # object will be empty until the remote connection is opened, as
199
- # indicated by the #REMOTE_ACTIVE flag.
200
- #
201
- # @return [Data] The remote properties.
202
- #
203
- def remote_properties
204
- data_to_object(Cproton.pn_connection_remote_properites(@impl))
146
+ # Idle-timeout advertised by the remote peer, in seconds.
147
+ # @return [Numeric] Idle-timeout advertised by the remote peer, in seconds.
148
+ # @return [nil] if the peer does not advertise an idle time-out
149
+ def idle_timeout()
150
+ if transport && (t = transport.remote_idle_timeout)
151
+ Rational(t, 1000) # More precise than Float
152
+ end
205
153
  end
206
154
 
207
- # Opens the connection.
208
- #
209
- def open
210
- object_to_data(@offered_capabilities,
211
- Cproton.pn_connection_offered_capabilities(@impl))
212
- object_to_data(@desired_capabilities,
213
- Cproton.pn_connection_desired_capabilities(@impl))
214
- object_to_data(@properties,
215
- Cproton.pn_connection_properties(@impl))
216
- Cproton.pn_connection_open(@impl)
155
+ # Session limit advertised by the remote peer. See {Connection#open :max_sessions}
156
+ # @return [Integer] maximum number of sessions per connection allowed by remote peer.
157
+ # @return [nil] no specific limit is set.
158
+ def max_sessions()
159
+ raise StateError, "connection not bound to transport" unless transport
160
+ max = transport.remote_channel_max
161
+ return max.zero? ? nil : max
217
162
  end
218
163
 
219
- # Closes the connection.
220
- #
221
- # Once this operation has completed, the #LOCAL_CLOSED state flag will be
222
- # set.
223
- #
224
- def close
225
- self._update_condition
164
+ # Maximum frame size, in bytes, advertised by the remote peer.
165
+ # See {Connection#open :max_frame_size}
166
+ # @return [Integer] maximum frame size
167
+ # @return [nil] no limit
168
+ def max_frame_size()
169
+ raise StateError, "connection not bound to transport" unless transport
170
+ max = transport.remote_max_frame
171
+ return max.zero? ? nil : max
172
+ end
173
+
174
+ # Closes the local end of the connection. The remote end may or may not be closed.
175
+ # @param error [Condition] Optional error condition to send with the close.
176
+ def close(error=nil)
177
+ Condition.assign(_local_condition, error)
226
178
  Cproton.pn_connection_close(@impl)
227
179
  end
228
180
 
@@ -239,99 +191,107 @@ module Qpid::Proton
239
191
  Cproton.pn_connection_state(@impl)
240
192
  end
241
193
 
242
- # Returns the session for this connection.
194
+ # Returns the default session for this connection.
243
195
  #
244
196
  # @return [Session] The session.
245
197
  #
246
- def session
247
- @session ||= Session.wrap(Cproton.pn_session(@impl))
198
+ def default_session
199
+ @session ||= open_session
248
200
  end
249
201
 
250
- # Returns the first session from the connection that matches the specified
251
- # state mask.
252
- #
253
- # Examines the state of each session owned by the connection, and returns
254
- # the first session that matches the given state mask. If the state mask
255
- # contains *both* local and remote flags, then an exact match against
256
- # those flags is performed. If the state mask contains only local *or*
257
- # remote flags, then a match occurs if a*any* of the local or remote flags
258
- # are set, respectively.
259
- #
260
- # @param mask [Integer] The state mask to be matched.
261
- #
262
- # @return [Session] The first matching session, or nil if none matched.
263
- #
264
- # @see Endpoint#LOCAL_UNINIT
265
- # @see Endpoint#LOCAL_ACTIVE
266
- # @see Endpoint#LOCAL_CLOSED
267
- # @see Endpoint#REMOTE_UNINIT
268
- # @see Endpoint#REMOTE_ACTIVE
269
- # @see Endpoint#REMOTE_CLOSED
270
- #
271
- def session_head(mask)
272
- Session.wrap(Cproton.pn_session_header(@impl, mask))
202
+ # @deprecated use #default_session()
203
+ deprecated_alias :session, :default_session
204
+
205
+ # Open a new session on this connection.
206
+ def open_session
207
+ s = Session.wrap(Cproton.pn_session(@impl))
208
+ s.open
209
+ return s
273
210
  end
274
211
 
275
- # Returns the first link that matches the given state mask.
276
- #
277
- # Examines the state of each link owned by the connection and returns the
278
- # first that matches the given state mask. If the state mask contains
279
- # *both* local and remote flags, then an exact match against those flags
280
- # is performed. If the state mask contains *only* local or remote flags,
281
- # then a match occurs if *any* of the local ore remote flags are set,
282
- # respectively.
283
- #
284
- # @param mask [Integer] The state mask to be matched.
285
- #
286
- # @return [Link] The first matching link, or nil if none matched.
287
- #
288
- # @see Endpoint#LOCAL_UNINIT
289
- # @see Endpoint#LOCAL_ACTIVE
290
- # @see Endpoint#LOCAL_CLOSED
291
- # @see Endpoint#REMOTE_UNINIT
292
- # @see Endpoint#REMOTE_ACTIVE
293
- # @see Endpoint#REMOTE_CLOSED
294
- #
212
+ # Open a sender on the default_session
213
+ # @option opts (see Session#open_sender)
214
+ def open_sender(opts=nil) default_session.open_sender(opts) end
215
+
216
+ # Open a on the default_session
217
+ # @option opts (see Session#open_receiver)
218
+ def open_receiver(opts=nil) default_session.open_receiver(opts) end
219
+
220
+ # @deprecated use {#each_session}
221
+ def session_head(mask)
222
+ deprecated __method__, "#each_session"
223
+ Session.wrap(Cproton.pn_session_head(@impl, mask))
224
+ end
225
+
226
+ # Get the sessions on this connection.
227
+ # @overload each_session
228
+ # @yieldparam s [Session] pass each session to block
229
+ # @overload each_session
230
+ # @return [Enumerator] enumerator over sessions
231
+ def each_session(&block)
232
+ return enum_for(:each_session) unless block_given?
233
+ s = Cproton.pn_session_head(@impl, 0);
234
+ while s
235
+ yield Session.wrap(s)
236
+ s = Cproton.pn_session_next(s, 0)
237
+ end
238
+ self
239
+ end
240
+
241
+ # @deprecated use {#each_link}
295
242
  def link_head(mask)
243
+ deprecated __method__, "#each_link"
296
244
  Link.wrap(Cproton.pn_link_head(@impl, mask))
297
245
  end
298
246
 
299
- # Extracts the first delivery on the connection that has pending
300
- # operations.
301
- #
302
- # A readable delivery indicates message data is waiting to be read. A
303
- # A writable delivery indcates that message data may be sent. An updated
304
- # delivery indicates that the delivery's disposition has changed.
305
- #
306
- # A delivery will never be *both* readable and writable, but it may be
307
- # both readable or writable and updated.
308
- #
309
- # @return [Delivery] The delivery, or nil if none are available.
310
- #
311
- # @see Delivery#next
312
- #
247
+ # Get the links on this connection.
248
+ # @overload each_link
249
+ # @yieldparam l [Link] pass each link to block
250
+ # @overload each_link
251
+ # @return [Enumerator] enumerator over links
252
+ def each_link
253
+ return enum_for(:each_link) unless block_given?
254
+ l = Cproton.pn_link_head(@impl, 0);
255
+ while l
256
+ yield Link.wrap(l)
257
+ l = Cproton.pn_link_next(l, 0)
258
+ end
259
+ self
260
+ end
261
+
262
+ # Get the {Sender} links - see {#each_link}
263
+ def each_sender() each_link.select { |l| l.sender? }; end
264
+
265
+ # Get the {Receiver} links - see {#each_link}
266
+ def each_receiver() each_link.select { |l| l.receiver? }; end
267
+
268
+ # @deprecated use {#MessagingHandler} to handle work
313
269
  def work_head
270
+ deprecated __method__
314
271
  Delivery.wrap(Cproton.pn_work_head(@impl))
315
272
  end
316
273
 
317
- # Returns the code for a connection error.
318
- #
319
- # @return [Integer] The error code.
320
- #
274
+ # @deprecated use {#condition}
321
275
  def error
276
+ deprecated __method__, "#condition"
322
277
  Cproton.pn_error_code(Cproton.pn_connection_error(@impl))
323
278
  end
324
279
 
325
- # @private
280
+ # @private Generate a unique link name, internal use only.
281
+ def link_name()
282
+ @link_prefix + "/" + (@link_count += 1).to_s(32)
283
+ end
284
+
285
+ protected
286
+
326
287
  def _local_condition
327
288
  Cproton.pn_connection_condition(@impl)
328
289
  end
329
290
 
330
- # @private
331
291
  def _remote_condition
332
292
  Cproton.pn_connection_remote_condition(@impl)
333
293
  end
334
294
 
295
+ proton_get :attachments
335
296
  end
336
-
337
297
  end