qpid_proton 0.9.0 → 0.10
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.
- checksums.yaml +4 -4
- data/lib/codec/data.rb +912 -0
- data/lib/codec/mapping.rb +169 -0
- data/lib/{qpid_proton/tracker.rb → core/base_handler.rb} +4 -15
- data/lib/core/connection.rb +328 -0
- data/lib/core/delivery.rb +271 -0
- data/lib/core/disposition.rb +158 -0
- data/lib/core/endpoint.rb +140 -0
- data/lib/{qpid_proton → core}/exceptions.rb +43 -2
- data/lib/core/link.rb +387 -0
- data/lib/core/message.rb +633 -0
- data/lib/core/receiver.rb +95 -0
- data/lib/core/sasl.rb +94 -0
- data/lib/core/selectable.rb +130 -0
- data/lib/core/sender.rb +76 -0
- data/lib/core/session.rb +163 -0
- data/lib/core/ssl.rb +164 -0
- data/lib/{qpid_proton/version.rb → core/ssl_details.rb} +7 -6
- data/lib/core/ssl_domain.rb +156 -0
- data/lib/core/terminus.rb +218 -0
- data/lib/core/transport.rb +411 -0
- data/lib/core/url.rb +77 -0
- data/lib/event/collector.rb +148 -0
- data/lib/event/event.rb +318 -0
- data/lib/event/event_base.rb +91 -0
- data/lib/event/event_type.rb +71 -0
- data/lib/handler/acking.rb +70 -0
- data/lib/handler/c_adaptor.rb +47 -0
- data/lib/handler/c_flow_controller.rb +33 -0
- data/lib/handler/endpoint_state_handler.rb +217 -0
- data/lib/handler/incoming_message_handler.rb +74 -0
- data/lib/handler/messaging_handler.rb +218 -0
- data/lib/handler/outgoing_message_handler.rb +98 -0
- data/lib/handler/wrapped_handler.rb +76 -0
- data/lib/messenger/messenger.rb +702 -0
- data/lib/messenger/subscription.rb +37 -0
- data/lib/messenger/tracker.rb +38 -0
- data/lib/messenger/tracker_status.rb +69 -0
- data/lib/qpid_proton.rb +106 -16
- data/lib/reactor/acceptor.rb +41 -0
- data/lib/reactor/backoff.rb +41 -0
- data/lib/reactor/connector.rb +98 -0
- data/lib/reactor/container.rb +272 -0
- data/lib/reactor/global_overrides.rb +44 -0
- data/lib/reactor/link_option.rb +90 -0
- data/lib/reactor/reactor.rb +198 -0
- data/lib/reactor/session_per_connection.rb +45 -0
- data/lib/reactor/ssl_config.rb +41 -0
- data/lib/reactor/task.rb +39 -0
- data/lib/{qpid_proton/subscription.rb → reactor/urls.rb} +12 -13
- data/lib/{qpid_proton → types}/array.rb +28 -29
- data/lib/types/described.rb +63 -0
- data/lib/{qpid_proton → types}/hash.rb +4 -3
- data/lib/types/strings.rb +62 -0
- data/lib/util/class_wrapper.rb +54 -0
- data/lib/util/condition.rb +45 -0
- data/lib/util/constants.rb +85 -0
- data/lib/util/engine.rb +82 -0
- data/lib/util/error_handler.rb +127 -0
- data/lib/util/handler.rb +41 -0
- data/lib/util/reactor.rb +32 -0
- data/lib/util/swig_helper.rb +114 -0
- data/lib/util/timeout.rb +50 -0
- data/lib/util/uuid.rb +32 -0
- data/lib/util/version.rb +30 -0
- data/lib/util/wrapper.rb +124 -0
- metadata +67 -21
- data/ext/cproton/cproton.c +0 -22196
- data/lib/qpid_proton/data.rb +0 -788
- data/lib/qpid_proton/described.rb +0 -66
- data/lib/qpid_proton/exception_handling.rb +0 -127
- data/lib/qpid_proton/filters.rb +0 -67
- data/lib/qpid_proton/mapping.rb +0 -170
- data/lib/qpid_proton/message.rb +0 -621
- data/lib/qpid_proton/messenger.rb +0 -702
- data/lib/qpid_proton/selectable.rb +0 -126
- data/lib/qpid_proton/strings.rb +0 -65
- data/lib/qpid_proton/tracker_status.rb +0 -73
@@ -17,9 +17,9 @@
|
|
17
17
|
# under the License.
|
18
18
|
#++
|
19
19
|
|
20
|
-
module Qpid
|
20
|
+
module Qpid
|
21
21
|
|
22
|
-
module Proton
|
22
|
+
module Proton
|
23
23
|
|
24
24
|
module Error
|
25
25
|
|
@@ -80,6 +80,47 @@ module Qpid # :nodoc:
|
|
80
80
|
class InProgressError < ProtonError
|
81
81
|
end
|
82
82
|
|
83
|
+
# Raised by instances of Transport.
|
84
|
+
#
|
85
|
+
class TransportError < ProtonError
|
86
|
+
end
|
87
|
+
|
88
|
+
# Raised by instances of SASL
|
89
|
+
#
|
90
|
+
class SASLError < TransportError
|
91
|
+
end
|
92
|
+
|
93
|
+
# Raised by Session.
|
94
|
+
#
|
95
|
+
class SessionError < ProtonError
|
96
|
+
end
|
97
|
+
|
98
|
+
# Raised when an attempt is made to change an attribute that is read-only.
|
99
|
+
#
|
100
|
+
class AttributeError < ProtonError
|
101
|
+
end
|
102
|
+
|
103
|
+
# Raised by link components.
|
104
|
+
#
|
105
|
+
class LinkError < ProtonError
|
106
|
+
end
|
107
|
+
|
108
|
+
class SSLError < TransportError
|
109
|
+
end
|
110
|
+
|
111
|
+
class SSLUnavailableError < SSLError
|
112
|
+
end
|
113
|
+
|
114
|
+
# Raised when a message is rejected.
|
115
|
+
#
|
116
|
+
class Reject < ProtonError
|
117
|
+
end
|
118
|
+
|
119
|
+
# Raised when a message is released.
|
120
|
+
#
|
121
|
+
class Release < ProtonError
|
122
|
+
end
|
123
|
+
|
83
124
|
end
|
84
125
|
|
85
126
|
end
|
data/lib/core/link.rb
ADDED
@@ -0,0 +1,387 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton
|
21
|
+
|
22
|
+
# The base for both Sender and Receiver, providing common functionality
|
23
|
+
# between both ends.
|
24
|
+
#
|
25
|
+
# A Link has a single parent Qpid::Proton::Session instance.
|
26
|
+
#
|
27
|
+
class Link < Endpoint
|
28
|
+
|
29
|
+
# The sender will send all deliveries initially unsettled.
|
30
|
+
SND_UNSETTLED = Cproton::PN_SND_UNSETTLED
|
31
|
+
# The sender will send all deliveries settled to the receiver.
|
32
|
+
SND_SETTLED = Cproton::PN_SND_SETTLED
|
33
|
+
# The sender may send a mixture of settled and unsettled deliveries.
|
34
|
+
SND_MIXED = Cproton::PN_SND_MIXED
|
35
|
+
|
36
|
+
# The receiver will settle deliveries regardless of what the sender does.
|
37
|
+
RCV_FIRST = Cproton::PN_RCV_FIRST
|
38
|
+
# The receiver will only settle deliveries after the sender settles.
|
39
|
+
RCV_SECOND = Cproton::PN_RCV_SECOND
|
40
|
+
|
41
|
+
# @private
|
42
|
+
include Util::SwigHelper
|
43
|
+
|
44
|
+
# @private
|
45
|
+
PROTON_METHOD_PREFIX = "pn_link"
|
46
|
+
|
47
|
+
# @!attribute [r] state
|
48
|
+
#
|
49
|
+
# Returns the endpoint state flags.
|
50
|
+
#
|
51
|
+
proton_caller :state
|
52
|
+
|
53
|
+
# @!method open
|
54
|
+
#
|
55
|
+
# Opens the link. Once this operation has completed, the state flag will be
|
56
|
+
# set.
|
57
|
+
#
|
58
|
+
# @see Endpoint::LOCAL_ACTIVE
|
59
|
+
proton_caller :open
|
60
|
+
|
61
|
+
# @!method close
|
62
|
+
#
|
63
|
+
# Closes the link.
|
64
|
+
#
|
65
|
+
# Once this operation has completed, the state flag will be set.
|
66
|
+
# This may be called without first calling #open, which is the equivalent to
|
67
|
+
# calling #open and then #close.
|
68
|
+
#
|
69
|
+
# @see Endpoint::LOCAL_CLOSED
|
70
|
+
proton_caller :close
|
71
|
+
|
72
|
+
# @!method detach
|
73
|
+
#
|
74
|
+
# Detaches the link.
|
75
|
+
proton_caller :detach
|
76
|
+
|
77
|
+
# Advance the current delivery to the next on the link.
|
78
|
+
#
|
79
|
+
# For sending links, this operation is used to finish sending message data
|
80
|
+
# for the current outgoing delivery and move on to the next outgoing
|
81
|
+
# delivery (if any).
|
82
|
+
#
|
83
|
+
# For receiving links, this operatoin is used to finish accessing message
|
84
|
+
# data from the current incoming delivery and move on to the next incoming
|
85
|
+
# delivery (if any).
|
86
|
+
#
|
87
|
+
# @return [Boolean] True if the current delivery was changed.
|
88
|
+
#
|
89
|
+
# @see #current
|
90
|
+
#
|
91
|
+
proton_caller :advance
|
92
|
+
|
93
|
+
proton_caller :unsettled
|
94
|
+
|
95
|
+
# @!attribute [r] credit
|
96
|
+
#
|
97
|
+
# Returns the credit balance for a link.
|
98
|
+
#
|
99
|
+
# Links use a credit based flow control scheme. Every receiver maintains a
|
100
|
+
# credit balance that corresponds to the number of deliveries that the
|
101
|
+
# receiver can accept at any given moment.
|
102
|
+
#
|
103
|
+
# As more capacity becomes available at the receiver, it adds credit to this
|
104
|
+
# balance and communicates the new balance to the sender. Whenever a
|
105
|
+
# delivery is sent/received, the credit balance maintained by the link is
|
106
|
+
# decremented by one.
|
107
|
+
#
|
108
|
+
# Once the credit balance at the sender reaches zero, the sender must pause
|
109
|
+
# sending until more credit is obtained from the receiver.
|
110
|
+
#
|
111
|
+
# NOte that a sending link may still be used to send deliveries eve if
|
112
|
+
# credit reaches zero. However those deliveries will end up being buffer by
|
113
|
+
# the link until enough credit is obtained from the receiver to send them
|
114
|
+
# over the wire. In this case the balance reported will go negative.
|
115
|
+
#
|
116
|
+
# @return [Fixnum] The credit balance.
|
117
|
+
#
|
118
|
+
# @see #flow
|
119
|
+
#
|
120
|
+
proton_caller :credit
|
121
|
+
|
122
|
+
# @!attribute [r] remote_credit
|
123
|
+
#
|
124
|
+
# Returns the remote view of the credit.
|
125
|
+
#
|
126
|
+
# The remote view of the credit for a link differs from the local view of
|
127
|
+
# credit for a link by the number of queued deliveries. In other words,
|
128
|
+
# remote credit is defined as credit - queued.
|
129
|
+
#
|
130
|
+
# @see #queued
|
131
|
+
# @see #credit
|
132
|
+
#
|
133
|
+
# @return [Fixnum] The remove view of the credit.
|
134
|
+
#
|
135
|
+
proton_caller :remote_credit
|
136
|
+
|
137
|
+
# @!attribute [r] available
|
138
|
+
#
|
139
|
+
# Returns the available deliveries hint for a link.
|
140
|
+
#
|
141
|
+
# The available count for a link provides a hint as to the number of
|
142
|
+
# deliveries that might be able to be sent if sufficient credit were issued
|
143
|
+
# by the receiving link endpoint.
|
144
|
+
#
|
145
|
+
# @return [Fixnum] The available deliveries hint.
|
146
|
+
#
|
147
|
+
# @see Sender#offered
|
148
|
+
#
|
149
|
+
proton_caller :available
|
150
|
+
|
151
|
+
# @!attribute [r] queued
|
152
|
+
#
|
153
|
+
# Returns the number of queued deliveries for a link.
|
154
|
+
#
|
155
|
+
# Links may queue deliveries for a number of reasons. For example, there may
|
156
|
+
# be insufficient credit to send them to the receiver, or they simply may
|
157
|
+
# not have yet had a chance to be written to the wire.
|
158
|
+
#
|
159
|
+
# @return [Fixnum] The number of queued deliveries.
|
160
|
+
#
|
161
|
+
# @see #credit
|
162
|
+
#
|
163
|
+
proton_caller :queued
|
164
|
+
|
165
|
+
# @!attribute [r] name
|
166
|
+
#
|
167
|
+
# Returns the name of the link.
|
168
|
+
#
|
169
|
+
# @return [String] The name.
|
170
|
+
#
|
171
|
+
proton_caller :name
|
172
|
+
|
173
|
+
# @!attribute [r] sender?
|
174
|
+
#
|
175
|
+
# Returns if the link is a sender.
|
176
|
+
#
|
177
|
+
# @return [Boolean] True if the link is a sender.
|
178
|
+
#
|
179
|
+
proton_reader :sender, :is_or_get => :is
|
180
|
+
|
181
|
+
# @!attribute [r] receiver?
|
182
|
+
#
|
183
|
+
# Returns if the link is a receiver.
|
184
|
+
#
|
185
|
+
# @return [Boolean] True if the link is a receiver.
|
186
|
+
#
|
187
|
+
proton_reader :receiver, :is_or_get => :is
|
188
|
+
|
189
|
+
# @private
|
190
|
+
proton_reader :attachments
|
191
|
+
|
192
|
+
# Drains excess credit.
|
193
|
+
#
|
194
|
+
# When a link is in drain mode, the sender must use all excess credit
|
195
|
+
# immediately and release any excess credit back to the receiver if there
|
196
|
+
# are no deliveries available to send.
|
197
|
+
#
|
198
|
+
# When invoked on a Sender that is in drain mode, this operation will
|
199
|
+
# release all excess credit back to the receiver and return the number of
|
200
|
+
# credits released back to the sender. If the link is not in drain mode,
|
201
|
+
# this operation is a noop.
|
202
|
+
#
|
203
|
+
# When invoked on a Receiver, this operation will return and reset the
|
204
|
+
# number of credits the sender has released back to it.
|
205
|
+
#
|
206
|
+
# @return [Fixnum] The number of credits drained.
|
207
|
+
#
|
208
|
+
proton_caller :drained
|
209
|
+
|
210
|
+
# @private
|
211
|
+
include Util::Wrapper
|
212
|
+
|
213
|
+
# @private
|
214
|
+
def self.wrap(impl)
|
215
|
+
return nil if impl.nil?
|
216
|
+
|
217
|
+
result = self.fetch_instance(impl, :pn_link_attachments)
|
218
|
+
return result unless result.nil?
|
219
|
+
if Cproton.pn_link_is_sender(impl)
|
220
|
+
return Sender.new(impl)
|
221
|
+
elsif Cproton.pn_link_is_receiver(impl)
|
222
|
+
return Receiver.new(impl)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# @private
|
227
|
+
def initialize(impl)
|
228
|
+
@impl = impl
|
229
|
+
self.class.store_instance(self, :pn_link_attachments)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns additional error information.
|
233
|
+
#
|
234
|
+
# Whenever a link operation fails (i.e., returns an error code) additional
|
235
|
+
# error details can be obtained from this method. Ther error object that is
|
236
|
+
# returned may also be used to clear the error condition.
|
237
|
+
#
|
238
|
+
# @return [Error] The error.
|
239
|
+
#
|
240
|
+
def error
|
241
|
+
Cproton.pn_link_error(@impl)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Returns the next link that matches the given state mask.
|
245
|
+
#
|
246
|
+
# @param state_mask [Fixnum] The state mask.
|
247
|
+
#
|
248
|
+
# @return [Sender, Receiver] The next link.
|
249
|
+
#
|
250
|
+
def next(state_mask)
|
251
|
+
return Link.wrap(Cproton.pn_link_next(@impl, state_mask))
|
252
|
+
end
|
253
|
+
|
254
|
+
# Returns the locally defined source terminus.
|
255
|
+
#
|
256
|
+
# @return [Terminus] The terminus
|
257
|
+
def source
|
258
|
+
Terminus.new(Cproton.pn_link_source(@impl))
|
259
|
+
end
|
260
|
+
|
261
|
+
# Returns the locally defined target terminus.
|
262
|
+
#
|
263
|
+
# @return [Terminus] The terminus.
|
264
|
+
#
|
265
|
+
def target
|
266
|
+
Terminus.new(Cproton.pn_link_target(@impl))
|
267
|
+
end
|
268
|
+
|
269
|
+
# Returns a representation of the remotely defined source terminus.
|
270
|
+
#
|
271
|
+
# @return [Terminus] The terminus.
|
272
|
+
#
|
273
|
+
def remote_source
|
274
|
+
Terminus.new(Cproton.pn_link_remote_source(@impl))
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns a representation of the remotely defined target terminus.
|
278
|
+
#
|
279
|
+
# @return [Terminus] The terminus.
|
280
|
+
#
|
281
|
+
def remote_target
|
282
|
+
Terminus.new(Cproton.pn_link_remote_target(@impl))
|
283
|
+
end
|
284
|
+
|
285
|
+
# Returns the parent session.
|
286
|
+
#
|
287
|
+
# @return [Session] The session.
|
288
|
+
#
|
289
|
+
def session
|
290
|
+
Session.wrap(Cproton.pn_link_session(@impl))
|
291
|
+
end
|
292
|
+
|
293
|
+
# Returns the parent connection.
|
294
|
+
#
|
295
|
+
# @return [Connection] The connection.
|
296
|
+
#
|
297
|
+
def connection
|
298
|
+
self.session.connection
|
299
|
+
end
|
300
|
+
|
301
|
+
# Returns the parent delivery.
|
302
|
+
#
|
303
|
+
# @return [Delivery] The delivery.
|
304
|
+
#
|
305
|
+
def delivery(tag)
|
306
|
+
Delivery.new(Cproton.pn_delivery(@impl, tag))
|
307
|
+
end
|
308
|
+
|
309
|
+
# Returns the current delivery.
|
310
|
+
#
|
311
|
+
# Each link maintains a sequence of deliveries in the order they were
|
312
|
+
# created, along with a reference to the *current* delivery. All send and
|
313
|
+
# receive operations on a link take place on the *current* delivery. If a
|
314
|
+
# link has no current delivery, the current delivery is automatically
|
315
|
+
# pointed to the *next* delivery created on the link.
|
316
|
+
#
|
317
|
+
# Once initialized, the current delivery remains the same until it is
|
318
|
+
# changed by advancing, or until it is settled.
|
319
|
+
#
|
320
|
+
# @see #next
|
321
|
+
# @see Delivery#settle
|
322
|
+
#
|
323
|
+
# @return [Delivery] The current delivery.
|
324
|
+
#
|
325
|
+
def current
|
326
|
+
Delivery.wrap(Cproton.pn_link_current(@impl))
|
327
|
+
end
|
328
|
+
|
329
|
+
# Sets the local sender settle mode.
|
330
|
+
#
|
331
|
+
# @param mode [Fixnum] The settle mode.
|
332
|
+
#
|
333
|
+
# @see #SND_UNSETTLED
|
334
|
+
# @see #SND_SETTLED
|
335
|
+
# @see #SND_MIXED
|
336
|
+
#
|
337
|
+
def snd_settle_mode=(mode)
|
338
|
+
Cproton.pn_link_set_snd_settle_mode(@impl, mode)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Returns the local sender settle mode.
|
342
|
+
#
|
343
|
+
# @return [Fixnum] The local sender settle mode.
|
344
|
+
#
|
345
|
+
# @see #snd_settle_mode
|
346
|
+
#
|
347
|
+
def snd_settle_mode
|
348
|
+
Cproton.pn_link_snd_settle_mode(@impl)
|
349
|
+
end
|
350
|
+
|
351
|
+
# Sets the local receiver settle mode.
|
352
|
+
#
|
353
|
+
# @param mode [Fixnum] The settle mode.
|
354
|
+
#
|
355
|
+
# @see #RCV_FIRST
|
356
|
+
# @see #RCV_SECOND
|
357
|
+
#
|
358
|
+
def rcv_settle_mode=(mode)
|
359
|
+
Cproton.pn_link_set_rcv_settle_mode(@impl, mode)
|
360
|
+
end
|
361
|
+
|
362
|
+
# Returns the local receiver settle mode.
|
363
|
+
#
|
364
|
+
# @return [Fixnum] The local receiver settle mode.
|
365
|
+
#
|
366
|
+
def rcv_settle_mode
|
367
|
+
Cproton.pn_link_rcv_settle_mode(@impl)
|
368
|
+
end
|
369
|
+
|
370
|
+
# @private
|
371
|
+
def _local_condition
|
372
|
+
Cproton.pn_link_condition(@impl)
|
373
|
+
end
|
374
|
+
|
375
|
+
# @private
|
376
|
+
def _remote_condition
|
377
|
+
Cproton.pn_link_remote_condition(@impl)
|
378
|
+
end
|
379
|
+
|
380
|
+
def ==(other)
|
381
|
+
other.respond_to?(:impl) &&
|
382
|
+
(Cproton.pni_address_of(other.impl) == Cproton.pni_address_of(@impl))
|
383
|
+
end
|
384
|
+
|
385
|
+
end
|
386
|
+
|
387
|
+
end
|
data/lib/core/message.rb
ADDED
@@ -0,0 +1,633 @@
|
|
1
|
+
#--
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module Qpid::Proton
|
21
|
+
|
22
|
+
# A Message represents an addressable quantity of data.
|
23
|
+
#
|
24
|
+
# ==== Message Body
|
25
|
+
#
|
26
|
+
# The message body can be set using the #body= method. The message will
|
27
|
+
# then attempt to determine how exactly to encode the content.
|
28
|
+
#
|
29
|
+
# ==== Examples
|
30
|
+
#
|
31
|
+
# To create a message for sending:
|
32
|
+
#
|
33
|
+
# # send a simple text message
|
34
|
+
# msg = Qpid::Proton::Message.new
|
35
|
+
# msg.body = "STATE: update"
|
36
|
+
#
|
37
|
+
# # send a binary chunk of data
|
38
|
+
# data = File.binread("/home/qpid/binfile.tar.gz")
|
39
|
+
# msg = Qpid::Proton::Message.new
|
40
|
+
# msg.body = Qpid::Proton::BinaryString.new(data)
|
41
|
+
#
|
42
|
+
class Message
|
43
|
+
|
44
|
+
# @private
|
45
|
+
def proton_send(sender, tag = nil)
|
46
|
+
dlv = sender.delivery(tag || sender.delivery_tag)
|
47
|
+
encoded = self.encode
|
48
|
+
sender.stream(encoded)
|
49
|
+
sender.advance
|
50
|
+
dlv.settle if sender.snd_settle_mode == Link::SND_SETTLED
|
51
|
+
return dlv
|
52
|
+
end
|
53
|
+
|
54
|
+
# Decodes a message from supplied AMQP data and returns the number
|
55
|
+
# of bytes consumed.
|
56
|
+
#
|
57
|
+
# ==== Options
|
58
|
+
#
|
59
|
+
# * encoded - the encoded data
|
60
|
+
#
|
61
|
+
def decode(encoded)
|
62
|
+
check(Cproton.pn_message_decode(@impl, encoded, encoded.length))
|
63
|
+
|
64
|
+
post_decode
|
65
|
+
end
|
66
|
+
|
67
|
+
def post_decode # :nodoc:
|
68
|
+
# decode elements from the message
|
69
|
+
@properties = {}
|
70
|
+
props = Codec::Data.new(Cproton::pn_message_properties(@impl))
|
71
|
+
if props.next
|
72
|
+
@properties = props.type.get(props)
|
73
|
+
end
|
74
|
+
@instructions = nil
|
75
|
+
insts = Codec::Data.new(Cproton::pn_message_instructions(@impl))
|
76
|
+
if insts.next
|
77
|
+
@instructions = insts.type.get(insts)
|
78
|
+
end
|
79
|
+
@annotations = nil
|
80
|
+
annts = Codec::Data.new(Cproton::pn_message_annotations(@impl))
|
81
|
+
if annts.next
|
82
|
+
@annotations = annts.type.get(annts)
|
83
|
+
end
|
84
|
+
@body = nil
|
85
|
+
body = Codec::Data.new(Cproton::pn_message_body(@impl))
|
86
|
+
if body.next
|
87
|
+
@body = body.type.get(body)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Encodes the message.
|
92
|
+
def encode
|
93
|
+
pre_encode
|
94
|
+
size = 16
|
95
|
+
loop do
|
96
|
+
error, data = Cproton::pn_message_encode(@impl, size)
|
97
|
+
if error == Qpid::Proton::Error::OVERFLOW
|
98
|
+
size *= 2
|
99
|
+
else
|
100
|
+
check(error)
|
101
|
+
return data
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def pre_encode # :nodoc:
|
107
|
+
# encode elements from the message
|
108
|
+
props = Codec::Data.new(Cproton::pn_message_properties(@impl))
|
109
|
+
props.clear
|
110
|
+
Codec::Mapping.for_class(@properties.class).put(props, @properties) unless @properties.empty?
|
111
|
+
insts = Codec::Data.new(Cproton::pn_message_instructions(@impl))
|
112
|
+
insts.clear
|
113
|
+
if !@instructions.nil?
|
114
|
+
mapping = Codec::Mapping.for_class(@instructions.class)
|
115
|
+
mapping.put(insts, @instructions)
|
116
|
+
end
|
117
|
+
annts = Codec::Data.new(Cproton::pn_message_annotations(@impl))
|
118
|
+
annts.clear
|
119
|
+
if !@annotations.nil?
|
120
|
+
mapping = Codec::Mapping.for_class(@annotations.class)
|
121
|
+
mapping.put(annts, @annotations, :keys => :SYMBOL)
|
122
|
+
end
|
123
|
+
body = Codec::Data.new(Cproton::pn_message_body(@impl))
|
124
|
+
body.clear
|
125
|
+
if !@body.nil?
|
126
|
+
mapping = Codec::Mapping.for_class(@body.class)
|
127
|
+
mapping.put(body, @body)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Creates a new +Message+ instance.
|
132
|
+
def initialize
|
133
|
+
@impl = Cproton.pn_message
|
134
|
+
ObjectSpace.define_finalizer(self, self.class.finalize!(@impl))
|
135
|
+
@properties = {}
|
136
|
+
@instructions = {}
|
137
|
+
@annotations = {}
|
138
|
+
@body = nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
tmp = Cproton.pn_string("")
|
143
|
+
Cproton.pn_inspect(@impl, tmp)
|
144
|
+
result = Cproton.pn_string_get(tmp)
|
145
|
+
Cproton.pn_free(tmp)
|
146
|
+
return result
|
147
|
+
end
|
148
|
+
|
149
|
+
# Invoked by garbage collection to clean up resources used
|
150
|
+
# by the underlying message implementation.
|
151
|
+
def self.finalize!(impl) # :nodoc:
|
152
|
+
proc {
|
153
|
+
Cproton.pn_message_free(impl)
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns the underlying message implementation.
|
158
|
+
def impl # :nodoc:
|
159
|
+
@impl
|
160
|
+
end
|
161
|
+
|
162
|
+
# Clears the state of the +Message+. This allows a single instance of
|
163
|
+
# +Message+ to be reused.
|
164
|
+
#
|
165
|
+
def clear
|
166
|
+
Cproton.pn_message_clear(@impl)
|
167
|
+
@properties.clear unless @properties.nil?
|
168
|
+
@instructions.clear unless @instructions.nil?
|
169
|
+
@annotations.clear unless @annotations.nil?
|
170
|
+
@body = nil
|
171
|
+
end
|
172
|
+
|
173
|
+
# Returns the most recent error number.
|
174
|
+
#
|
175
|
+
def errno
|
176
|
+
Cproton.pn_message_errno(@impl)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Returns the most recent error message.
|
180
|
+
#
|
181
|
+
def error
|
182
|
+
Cproton.pn_error_text(Cproton.pn_message_error(@impl))
|
183
|
+
end
|
184
|
+
|
185
|
+
# Returns whether there is currently an error reported.
|
186
|
+
#
|
187
|
+
def error?
|
188
|
+
!Cproton.pn_message_errno(@impl).zero?
|
189
|
+
end
|
190
|
+
|
191
|
+
# Sets the durable flag.
|
192
|
+
#
|
193
|
+
# See ::durable for more details on message durability.
|
194
|
+
#
|
195
|
+
# ==== Options
|
196
|
+
#
|
197
|
+
# * state - the durable state
|
198
|
+
#
|
199
|
+
def durable=(state)
|
200
|
+
raise TypeError.new("state cannot be nil") if state.nil?
|
201
|
+
Cproton.pn_message_set_durable(@impl, state)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns the durable property.
|
205
|
+
#
|
206
|
+
# The durable property indicates that the emessage should be held durably
|
207
|
+
# by any intermediaries taking responsibility for the message.
|
208
|
+
#
|
209
|
+
# ==== Examples
|
210
|
+
#
|
211
|
+
# msg = Qpid::Proton::Message.new
|
212
|
+
# msg.durable = true
|
213
|
+
#
|
214
|
+
def durable
|
215
|
+
Cproton.pn_message_is_durable(@impl)
|
216
|
+
end
|
217
|
+
|
218
|
+
# Sets the priority.
|
219
|
+
#
|
220
|
+
# +NOTE:+ Priority values are limited to the range [0,255].
|
221
|
+
#
|
222
|
+
# ==== Options
|
223
|
+
#
|
224
|
+
# * priority - the priority value
|
225
|
+
#
|
226
|
+
def priority=(priority)
|
227
|
+
raise TypeError.new("invalid priority: #{priority}") if priority.nil? || !([Float, Fixnum].include?(priority.class))
|
228
|
+
raise RangeError.new("priority out of range: #{priority}") if ((priority > 255) || (priority < 0))
|
229
|
+
Cproton.pn_message_set_priority(@impl, priority.floor)
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns the priority.
|
233
|
+
#
|
234
|
+
def priority
|
235
|
+
Cproton.pn_message_get_priority(@impl)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Sets the time-to-live for the message.
|
239
|
+
#
|
240
|
+
# ==== Options
|
241
|
+
#
|
242
|
+
# * time - the time in milliseconds
|
243
|
+
#
|
244
|
+
def ttl=(time)
|
245
|
+
raise TypeError.new("invalid ttl: #{time}") if time.nil? || !([Float, Fixnum].include?(time.class))
|
246
|
+
raise RangeError.new("time out of range: #{time}") if ((time < 0))
|
247
|
+
Cproton.pn_message_set_ttl(@impl, time.floor)
|
248
|
+
end
|
249
|
+
|
250
|
+
# Returns the time-to-live, in milliseconds.
|
251
|
+
#
|
252
|
+
def ttl
|
253
|
+
Cproton.pn_message_get_ttl(@impl)
|
254
|
+
end
|
255
|
+
|
256
|
+
# Sets whether this is the first time the message was acquired.
|
257
|
+
#
|
258
|
+
# See ::first_acquirer? for more details.
|
259
|
+
#
|
260
|
+
# ==== Options
|
261
|
+
#
|
262
|
+
# * state - true if claiming the message
|
263
|
+
#
|
264
|
+
def first_acquirer=(state)
|
265
|
+
raise TypeError.new("invalid state: #{state}") if state.nil? || !([TrueClass, FalseClass].include?(state.class))
|
266
|
+
Cproton.pn_message_set_first_acquirer(@impl, state)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Sets the delivery count for the message.
|
270
|
+
#
|
271
|
+
# See ::delivery_count for more details.
|
272
|
+
#
|
273
|
+
# ==== Options
|
274
|
+
#
|
275
|
+
# * count - the delivery count
|
276
|
+
#
|
277
|
+
def delivery_count=(count)
|
278
|
+
raise ::ArgumentError.new("invalid count: #{count}") if count.nil? || !([Float, Fixnum].include?(count.class))
|
279
|
+
raise RangeError.new("count out of range: #{count}") if count < 0
|
280
|
+
|
281
|
+
Cproton.pn_message_set_delivery_count(@impl, count.floor)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Returns the delivery count for the message.
|
285
|
+
#
|
286
|
+
# This is the number of delivery attempts for the given message.
|
287
|
+
#
|
288
|
+
def delivery_count
|
289
|
+
Cproton.pn_message_get_delivery_count(@impl)
|
290
|
+
end
|
291
|
+
|
292
|
+
# Returns whether this is the first acquirer.
|
293
|
+
#
|
294
|
+
#
|
295
|
+
def first_acquirer?
|
296
|
+
Cproton.pn_message_is_first_acquirer(@impl)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Sets the message id.
|
300
|
+
#
|
301
|
+
# ==== Options
|
302
|
+
#
|
303
|
+
# * id = the id
|
304
|
+
#
|
305
|
+
def id=(id)
|
306
|
+
Cproton.pn_message_set_id(@impl, id)
|
307
|
+
end
|
308
|
+
|
309
|
+
# Returns the message id.
|
310
|
+
#
|
311
|
+
def id
|
312
|
+
Cproton.pn_message_get_id(@impl)
|
313
|
+
end
|
314
|
+
|
315
|
+
# Sets the user id.
|
316
|
+
#
|
317
|
+
# ==== Options
|
318
|
+
#
|
319
|
+
# * id - the user id
|
320
|
+
#
|
321
|
+
def user_id=(id)
|
322
|
+
Cproton.pn_message_set_user_id(@impl, id)
|
323
|
+
end
|
324
|
+
|
325
|
+
# Returns the user id.
|
326
|
+
#
|
327
|
+
def user_id
|
328
|
+
Cproton.pn_message_get_user_id(@impl)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Sets the destination address.
|
332
|
+
#
|
333
|
+
# ==== Options
|
334
|
+
#
|
335
|
+
# * address - the address
|
336
|
+
#
|
337
|
+
def address=(address)
|
338
|
+
Cproton.pn_message_set_address(@impl, address)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Returns the destination address.
|
342
|
+
#
|
343
|
+
def address
|
344
|
+
Cproton.pn_message_get_address(@impl)
|
345
|
+
end
|
346
|
+
|
347
|
+
# Sets the subject.
|
348
|
+
#
|
349
|
+
# ==== Options
|
350
|
+
#
|
351
|
+
# * subject - the subject
|
352
|
+
#
|
353
|
+
def subject=(subject)
|
354
|
+
Cproton.pn_message_set_subject(@impl, subject)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Returns the subject
|
358
|
+
#
|
359
|
+
def subject
|
360
|
+
Cproton.pn_message_get_subject(@impl)
|
361
|
+
end
|
362
|
+
|
363
|
+
# Sets the reply-to address.
|
364
|
+
#
|
365
|
+
# ==== Options
|
366
|
+
#
|
367
|
+
# * address - the reply-to address
|
368
|
+
#
|
369
|
+
def reply_to=(address)
|
370
|
+
Cproton.pn_message_set_reply_to(@impl, address)
|
371
|
+
end
|
372
|
+
|
373
|
+
# Returns the reply-to address
|
374
|
+
#
|
375
|
+
def reply_to
|
376
|
+
Cproton.pn_message_get_reply_to(@impl)
|
377
|
+
end
|
378
|
+
|
379
|
+
# Sets the correlation id.
|
380
|
+
#
|
381
|
+
# ==== Options
|
382
|
+
#
|
383
|
+
# * id - the correlation id
|
384
|
+
#
|
385
|
+
def correlation_id=(id)
|
386
|
+
Cproton.pn_message_set_correlation_id(@impl, id)
|
387
|
+
end
|
388
|
+
|
389
|
+
# Returns the correlation id.
|
390
|
+
#
|
391
|
+
def correlation_id
|
392
|
+
Cproton.pn_message_get_correlation_id(@impl)
|
393
|
+
end
|
394
|
+
|
395
|
+
# Sets the content type.
|
396
|
+
#
|
397
|
+
# ==== Options
|
398
|
+
#
|
399
|
+
# * content_type - the content type
|
400
|
+
#
|
401
|
+
def content_type=(content_type)
|
402
|
+
Cproton.pn_message_set_content_type(@impl, content_type)
|
403
|
+
end
|
404
|
+
|
405
|
+
# Returns the content type
|
406
|
+
#
|
407
|
+
def content_type
|
408
|
+
Cproton.pn_message_get_content_type(@impl)
|
409
|
+
end
|
410
|
+
|
411
|
+
# Sets the message content.
|
412
|
+
#
|
413
|
+
# *WARNING:* This method has been deprecated. Please use #body= instead to
|
414
|
+
# set the content of a message.
|
415
|
+
#
|
416
|
+
# ==== Options
|
417
|
+
#
|
418
|
+
# * content - the content
|
419
|
+
#
|
420
|
+
def content=(content)
|
421
|
+
Cproton.pn_message_load(@impl, content)
|
422
|
+
end
|
423
|
+
|
424
|
+
# Returns the message content.
|
425
|
+
#
|
426
|
+
# *WARNING:* This method has been deprecated. Please use #body instead to
|
427
|
+
# retrieve the content of a message.
|
428
|
+
#
|
429
|
+
def content
|
430
|
+
size = 16
|
431
|
+
loop do
|
432
|
+
result = Cproton.pn_message_save(@impl, size)
|
433
|
+
error = result[0]
|
434
|
+
data = result[1]
|
435
|
+
if error == Qpid::Proton::Error::OVERFLOW
|
436
|
+
size = size * 2
|
437
|
+
else
|
438
|
+
check(error)
|
439
|
+
return data
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
# Sets the content encoding type.
|
445
|
+
#
|
446
|
+
# ==== Options
|
447
|
+
#
|
448
|
+
# * encoding - the content encoding
|
449
|
+
#
|
450
|
+
def content_encoding=(encoding)
|
451
|
+
Cproton.pn_message_set_content_encoding(@impl, encoding)
|
452
|
+
end
|
453
|
+
|
454
|
+
# Returns the content encoding type.
|
455
|
+
#
|
456
|
+
def content_encoding
|
457
|
+
Cproton.pn_message_get_content_encoding(@impl)
|
458
|
+
end
|
459
|
+
|
460
|
+
# Sets the expiration time.
|
461
|
+
#
|
462
|
+
# ==== Options
|
463
|
+
#
|
464
|
+
# * time - the expiry time
|
465
|
+
#
|
466
|
+
def expires=(time)
|
467
|
+
raise TypeError.new("invalid expiry time: #{time}") if time.nil?
|
468
|
+
raise ::ArgumentError.new("expiry time cannot be negative: #{time}") if time < 0
|
469
|
+
Cproton.pn_message_set_expiry_time(@impl, time)
|
470
|
+
end
|
471
|
+
|
472
|
+
# Returns the expiration time.
|
473
|
+
#
|
474
|
+
def expires
|
475
|
+
Cproton.pn_message_get_expiry_time(@impl)
|
476
|
+
end
|
477
|
+
|
478
|
+
# Sets the creation time.
|
479
|
+
#
|
480
|
+
# ==== Options
|
481
|
+
#
|
482
|
+
# * time - the creation time
|
483
|
+
#
|
484
|
+
def creation_time=(time)
|
485
|
+
raise TypeError.new("invalid time: #{time}") if time.nil?
|
486
|
+
raise ::ArgumentError.new("time cannot be negative") if time < 0
|
487
|
+
Cproton.pn_message_set_creation_time(@impl, time)
|
488
|
+
end
|
489
|
+
|
490
|
+
# Returns the creation time.
|
491
|
+
#
|
492
|
+
def creation_time
|
493
|
+
Cproton.pn_message_get_creation_time(@impl)
|
494
|
+
end
|
495
|
+
|
496
|
+
# Sets the group id.
|
497
|
+
#
|
498
|
+
# ==== Options
|
499
|
+
#
|
500
|
+
# * id - the group id
|
501
|
+
#
|
502
|
+
def group_id=(id)
|
503
|
+
Cproton.pn_message_set_group_id(@impl, id)
|
504
|
+
end
|
505
|
+
|
506
|
+
# Returns the group id.
|
507
|
+
#
|
508
|
+
def group_id
|
509
|
+
Cproton.pn_message_get_group_id(@impl)
|
510
|
+
end
|
511
|
+
|
512
|
+
# Sets the group sequence number.
|
513
|
+
#
|
514
|
+
# ==== Options
|
515
|
+
#
|
516
|
+
# * seq - the sequence number
|
517
|
+
#
|
518
|
+
def group_sequence=(seq)
|
519
|
+
raise TypeError.new("invalid seq: #{seq}") if seq.nil?
|
520
|
+
Cproton.pn_message_set_group_sequence(@impl, seq)
|
521
|
+
end
|
522
|
+
|
523
|
+
# Returns the group sequence number.
|
524
|
+
#
|
525
|
+
def group_sequence
|
526
|
+
Cproton.pn_message_get_group_sequence(@impl)
|
527
|
+
end
|
528
|
+
|
529
|
+
# Sets the reply-to group id.
|
530
|
+
#
|
531
|
+
# ==== Options
|
532
|
+
#
|
533
|
+
# * id - the id
|
534
|
+
#
|
535
|
+
def reply_to_group_id=(id)
|
536
|
+
Cproton.pn_message_set_reply_to_group_id(@impl, id)
|
537
|
+
end
|
538
|
+
|
539
|
+
# Returns the reply-to group id.
|
540
|
+
#
|
541
|
+
def reply_to_group_id
|
542
|
+
Cproton.pn_message_get_reply_to_group_id(@impl)
|
543
|
+
end
|
544
|
+
|
545
|
+
# Returns the list of property names for associated with this message.
|
546
|
+
#
|
547
|
+
# ==== Examples
|
548
|
+
#
|
549
|
+
# msg.properties.each do |name|
|
550
|
+
# end
|
551
|
+
#
|
552
|
+
def properties
|
553
|
+
@properties
|
554
|
+
end
|
555
|
+
|
556
|
+
# Replaces the entire set of properties with the specified hash.
|
557
|
+
#
|
558
|
+
def properties=(properties)
|
559
|
+
@properties = properties
|
560
|
+
end
|
561
|
+
|
562
|
+
# Assigns the value given to the named property.
|
563
|
+
#
|
564
|
+
# ==== Arguments
|
565
|
+
#
|
566
|
+
# * name - the property name
|
567
|
+
# * value - the property value
|
568
|
+
#
|
569
|
+
def []=(name, value)
|
570
|
+
@properties[name] = value
|
571
|
+
end
|
572
|
+
|
573
|
+
# Retrieves the value for the specified property name. If not found, then
|
574
|
+
# it returns nil.
|
575
|
+
#
|
576
|
+
def [](name)
|
577
|
+
@properties[name]
|
578
|
+
end
|
579
|
+
|
580
|
+
# Deletes the named property.
|
581
|
+
#
|
582
|
+
def delete_property(name)
|
583
|
+
@properties.delete(name)
|
584
|
+
end
|
585
|
+
|
586
|
+
# Returns the instructions for this message.
|
587
|
+
#
|
588
|
+
def instructions
|
589
|
+
@instructions
|
590
|
+
end
|
591
|
+
|
592
|
+
# Assigns instructions to this message.
|
593
|
+
#
|
594
|
+
def instructions=(instr)
|
595
|
+
@instructions = instr
|
596
|
+
end
|
597
|
+
|
598
|
+
# Returns the annotations for this message.
|
599
|
+
#
|
600
|
+
def annotations
|
601
|
+
@annotations
|
602
|
+
end
|
603
|
+
|
604
|
+
# Assigns annotations to this message.
|
605
|
+
#
|
606
|
+
def annotations=(annotations)
|
607
|
+
@annotations = annotations
|
608
|
+
end
|
609
|
+
|
610
|
+
# Returns the body property of the message.
|
611
|
+
#
|
612
|
+
def body
|
613
|
+
@body
|
614
|
+
end
|
615
|
+
|
616
|
+
# Assigns a new value to the body of the message.
|
617
|
+
#
|
618
|
+
def body=(body)
|
619
|
+
@body = body
|
620
|
+
end
|
621
|
+
|
622
|
+
private
|
623
|
+
|
624
|
+
def check(err) # :nodoc:
|
625
|
+
if err < 0
|
626
|
+
raise DataError, "[#{err}]: #{Cproton.pn_message_error(@data)}"
|
627
|
+
else
|
628
|
+
return err
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
end
|