qpid_proton 0.5 → 0.6
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/ChangeLog +9 -0
- data/ext/cproton/cproton.c +664 -223
- data/lib/qpid_proton/data.rb +8 -0
- data/lib/qpid_proton/exception_handling.rb +9 -0
- data/lib/qpid_proton/exceptions.rb +9 -0
- data/lib/qpid_proton/messenger.rb +239 -30
- data/lib/qpid_proton/tracker.rb +0 -4
- data/lib/qpid_proton/tracker_status.rb +1 -0
- metadata +3 -3
data/lib/qpid_proton/data.rb
CHANGED
@@ -111,6 +111,14 @@ module Qpid
|
|
111
111
|
}
|
112
112
|
end
|
113
113
|
|
114
|
+
def to_s
|
115
|
+
tmp = Cproton.pn_string("")
|
116
|
+
Cproton.pn_inspect(@data, tmp)
|
117
|
+
result = Cproton.pn_string_get(tmp)
|
118
|
+
Cproton.pn_free(tmp)
|
119
|
+
return result
|
120
|
+
end
|
121
|
+
|
114
122
|
# Clears the object.
|
115
123
|
def clear
|
116
124
|
Cproton.pn_data_clear(@data)
|
@@ -29,8 +29,11 @@ module Qpid
|
|
29
29
|
#
|
30
30
|
# Expects the class to provide an +error+ method.
|
31
31
|
def check_for_error(code)
|
32
|
+
|
32
33
|
raise ::ArgumentError.new("Invalid error code: #{code}") if code.nil?
|
33
34
|
|
35
|
+
return code if code > 0
|
36
|
+
|
34
37
|
case(code)
|
35
38
|
|
36
39
|
when Qpid::Proton::Error::NONE
|
@@ -57,6 +60,12 @@ module Qpid
|
|
57
60
|
when Qpid::Proton::Error::INPROGRESS
|
58
61
|
return
|
59
62
|
|
63
|
+
when Qpid::Proton::Error::INTERRUPTED
|
64
|
+
raise Qpid::Proton::InterruptedError.new(self.error)
|
65
|
+
|
66
|
+
when Qpid::Proton::Error::INPROGRESS
|
67
|
+
raise Qpid::Proton::InProgressError.new(self.error)
|
68
|
+
|
60
69
|
else
|
61
70
|
|
62
71
|
raise ::ArgumentError.new("Unknown error code: #{code}")
|
@@ -31,6 +31,7 @@ module Qpid
|
|
31
31
|
STATE = Cproton::PN_STATE_ERR
|
32
32
|
ARGUMENT = Cproton::PN_ARG_ERR
|
33
33
|
TIMEOUT = Cproton::PN_TIMEOUT
|
34
|
+
INTERRUPTED = Cproton::PN_INTR
|
34
35
|
INPROGRESS = Cproton::PN_INPROGRESS
|
35
36
|
|
36
37
|
end
|
@@ -65,6 +66,14 @@ module Qpid
|
|
65
66
|
class TimeoutError < ProtonError
|
66
67
|
end
|
67
68
|
|
69
|
+
# Represents an interrupting during a blocking I/O operation.
|
70
|
+
#
|
71
|
+
class InterruptedError < ProtonError
|
72
|
+
end
|
73
|
+
|
74
|
+
class InProgressError < ProtonError
|
75
|
+
end
|
76
|
+
|
68
77
|
end
|
69
78
|
|
70
79
|
end
|
@@ -21,10 +21,39 @@ module Qpid
|
|
21
21
|
|
22
22
|
module Proton
|
23
23
|
|
24
|
-
#
|
25
|
-
# receiving
|
24
|
+
# The +Messenger+ class defines a high level interface for
|
25
|
+
# sending and receiving Messages. Every Messenger contains
|
26
|
+
# a single logical queue of incoming messages and a single
|
27
|
+
# logical queue of outgoing messages. These messages in these
|
28
|
+
# queues may be destined for, or originate from, a variety of
|
29
|
+
# addresses.
|
26
30
|
#
|
27
|
-
#
|
31
|
+
# The messenger interface is single-threaded. All methods
|
32
|
+
# except one ( #interrupt ) are intended to be used from within
|
33
|
+
# the messenger thread.
|
34
|
+
#
|
35
|
+
# === Sending & Receiving Messages
|
36
|
+
#
|
37
|
+
# The Messenger class works in conjuction with the Message class. The
|
38
|
+
# Message class is a mutable holder of message content.
|
39
|
+
#
|
40
|
+
# The put method copies its Message to the outgoing queue, and may
|
41
|
+
# send queued messages if it can do so without blocking. The send
|
42
|
+
# method blocks until it has sent the requested number of messages,
|
43
|
+
# or until a timeout interrupts the attempt.
|
44
|
+
#
|
45
|
+
# Similarly, the recv method receives messages into the incoming
|
46
|
+
# queue, and may block as it attempts to receive the requested number
|
47
|
+
# of messages, or until timeout is reached. It may receive fewer
|
48
|
+
# than the requested number. The get method pops the
|
49
|
+
# eldest Message off the incoming queue and copies it into the Message
|
50
|
+
# object that you supply. It will not block.
|
51
|
+
#
|
52
|
+
# The blocking attribute allows you to turn off blocking behavior entirely,
|
53
|
+
# in which case send and recv will do whatever they can without
|
54
|
+
# blocking, and then return. You can then look at the number
|
55
|
+
# of incoming and outgoing messages to see how much outstanding work
|
56
|
+
# still remains.
|
28
57
|
#
|
29
58
|
class Messenger
|
30
59
|
|
@@ -56,6 +85,23 @@ module Qpid
|
|
56
85
|
Cproton.pn_messenger_name(@impl)
|
57
86
|
end
|
58
87
|
|
88
|
+
# This property contains the password for the Messenger.private_key
|
89
|
+
# file, or +nil+ if the file is not encrypted.
|
90
|
+
#
|
91
|
+
# ==== Arguments
|
92
|
+
#
|
93
|
+
# * password - the password
|
94
|
+
#
|
95
|
+
def password=(password)
|
96
|
+
check_for_error(Cproton.pn_messenger_set_password(@impl, password))
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the password property for the Messenger.private_key file.
|
100
|
+
#
|
101
|
+
def password
|
102
|
+
Cproton.pn_messenger_get_password(@impl)
|
103
|
+
end
|
104
|
+
|
59
105
|
# Sets the timeout period, in milliseconds.
|
60
106
|
#
|
61
107
|
# A negative timeout period implies an infinite timeout.
|
@@ -75,6 +121,12 @@ module Qpid
|
|
75
121
|
Cproton.pn_messenger_get_timeout(@impl)
|
76
122
|
end
|
77
123
|
|
124
|
+
# Blocking Attribute
|
125
|
+
#
|
126
|
+
# Enable or disable blocking behavior during message sending
|
127
|
+
# and receiving. This affects every blocking call, with the
|
128
|
+
# exception of work(). Currently, the affected calls are
|
129
|
+
# send, recv, and stop.
|
78
130
|
def blocking
|
79
131
|
Cproton.pn_mesenger_is_blocking(@impl)
|
80
132
|
end
|
@@ -101,8 +153,9 @@ module Qpid
|
|
101
153
|
Cproton.pn_error_text(Cproton.pn_messenger_error(@impl))
|
102
154
|
end
|
103
155
|
|
104
|
-
#
|
105
|
-
#
|
156
|
+
# Currently a no-op placeholder.
|
157
|
+
# For future compatibility, do not send or recv messages
|
158
|
+
# before starting the +Messenger+.
|
106
159
|
#
|
107
160
|
def start
|
108
161
|
check_for_error(Cproton.pn_messenger_start(@impl))
|
@@ -115,11 +168,22 @@ module Qpid
|
|
115
168
|
check_for_error(Cproton.pn_messenger_stop(@impl))
|
116
169
|
end
|
117
170
|
|
171
|
+
# Returns true iff a Messenger is in the stopped state.
|
172
|
+
# This function does not block.
|
173
|
+
#
|
118
174
|
def stopped
|
119
175
|
Cproton.pn_messenger_stopped(@impl)
|
120
176
|
end
|
121
177
|
|
122
|
-
# Subscribes the
|
178
|
+
# Subscribes the Messenger to messages originating from the
|
179
|
+
# specified source. The source is an address as specified in the
|
180
|
+
# Messenger introduction with the following addition. If the
|
181
|
+
# domain portion of the address begins with the '~' character, the
|
182
|
+
# Messenger will interpret the domain as host/port, bind to it,
|
183
|
+
# and listen for incoming messages. For example "~0.0.0.0",
|
184
|
+
# "amqp://~0.0.0.0" will all bind to any local interface and
|
185
|
+
# listen for incoming messages. Ad address of # "amqps://~0.0.0.0"
|
186
|
+
# will only permit incoming SSL connections.
|
123
187
|
#
|
124
188
|
def subscribe(address)
|
125
189
|
raise TypeError.new("invalid address: #{address}") if address.nil?
|
@@ -131,7 +195,10 @@ module Qpid
|
|
131
195
|
# Path to a certificate file for the +Messenger+.
|
132
196
|
#
|
133
197
|
# This certificate is used when the +Messenger+ accepts or establishes
|
134
|
-
# SSL/TLS connections.
|
198
|
+
# SSL/TLS connections. This property must be specified for the
|
199
|
+
# Messenger to accept incoming SSL/TLS connections and to establish
|
200
|
+
# client authenticated outgoing SSL/TLS connection. Non client authenticated
|
201
|
+
# outgoing SSL/TLS connections do not require this property.
|
135
202
|
#
|
136
203
|
# ==== Options
|
137
204
|
#
|
@@ -151,7 +218,8 @@ module Qpid
|
|
151
218
|
#
|
152
219
|
# The property must be specified for the +Messenger+ to accept incoming
|
153
220
|
# SSL/TLS connections and to establish client authenticated outgoing
|
154
|
-
# SSL/TLS connections.
|
221
|
+
# SSL/TLS connections. Non client authenticated SSL/TLS connections
|
222
|
+
# do not require this property.
|
155
223
|
#
|
156
224
|
# ==== Options
|
157
225
|
#
|
@@ -185,9 +253,15 @@ module Qpid
|
|
185
253
|
Cproton.pn_messenger_get_trusted_certificates(@impl)
|
186
254
|
end
|
187
255
|
|
188
|
-
#
|
256
|
+
# Places the content contained in the message onto the outgoing
|
257
|
+
# queue of the Messenger.
|
189
258
|
#
|
190
|
-
#
|
259
|
+
# This method will never block, however it will send any unblocked
|
260
|
+
# Messages in the outgoing queue immediately and leave any blocked
|
261
|
+
# Messages remaining in the outgoing queue.
|
262
|
+
# The send call may then be used to block until the outgoing queue
|
263
|
+
# is empty. The outgoing attribute may be used to check the depth
|
264
|
+
# of the outgoing queue.
|
191
265
|
#
|
192
266
|
# ==== Options
|
193
267
|
#
|
@@ -202,14 +276,22 @@ module Qpid
|
|
202
276
|
return outgoing_tracker
|
203
277
|
end
|
204
278
|
|
205
|
-
#
|
206
|
-
#
|
279
|
+
# This call will block until the indicated number of messages
|
280
|
+
# have been sent, or until the operation times out.
|
281
|
+
# If n is -1 this call will block until all outgoing messages
|
282
|
+
# have been sent. If n is 0 then this call will send whatever
|
283
|
+
# it can without blocking.
|
207
284
|
#
|
208
285
|
def send(n = -1)
|
209
286
|
check_for_error(Cproton.pn_messenger_send(@impl, n))
|
210
287
|
end
|
211
288
|
|
212
|
-
#
|
289
|
+
# Moves the message from the head of the incoming message queue into
|
290
|
+
# the supplied message object. Any content in the supplied message
|
291
|
+
# will be overwritten.
|
292
|
+
# A tracker for the incoming Message is returned. The tracker can
|
293
|
+
# later be used to communicate your acceptance or rejection of the
|
294
|
+
# Message.
|
213
295
|
#
|
214
296
|
# If no message is provided in the argument, then one is created. In
|
215
297
|
# either case, the one returned will be the fetched message.
|
@@ -230,8 +312,11 @@ module Qpid
|
|
230
312
|
return incoming_tracker
|
231
313
|
end
|
232
314
|
|
233
|
-
# Receives up to
|
234
|
-
#
|
315
|
+
# Receives up to limit messages into the incoming queue. If no value
|
316
|
+
# for limit is supplied, this call will receive as many messages as it
|
317
|
+
# can buffer internally. If the Messenger is in blocking mode, this
|
318
|
+
# call will block until at least one Message is available in the
|
319
|
+
# incoming queue.
|
235
320
|
#
|
236
321
|
# Options ====
|
237
322
|
#
|
@@ -245,6 +330,28 @@ module Qpid
|
|
245
330
|
Cproton.pn_messenger_receiving(@impl)
|
246
331
|
end
|
247
332
|
|
333
|
+
# Attempts interrupting of the messenger thread.
|
334
|
+
#
|
335
|
+
# The Messenger interface is single-threaded, and this is the only
|
336
|
+
# function intended to be called from outside of is thread.
|
337
|
+
#
|
338
|
+
# Call this from a non-Messenger thread to interrupt it while it
|
339
|
+
# is blocking. This will cause a ::InterruptError to be raised.
|
340
|
+
#
|
341
|
+
# If there is no currently blocking call, then the next blocking
|
342
|
+
# call will be affected, even if it is within the same thread that
|
343
|
+
# originated the interrupt.
|
344
|
+
#
|
345
|
+
def interrupt
|
346
|
+
check_for_error(Cproton.pn_messenger_interrupt(@impl))
|
347
|
+
end
|
348
|
+
|
349
|
+
# Sends or receives any outstanding messages queued for a Messenger.
|
350
|
+
#
|
351
|
+
# This will block for the indicated timeout. This method may also do I/O
|
352
|
+
# other than sending and receiving messages. For example, closing
|
353
|
+
# connections after stop() has been called.
|
354
|
+
#
|
248
355
|
def work(timeout=-1)
|
249
356
|
err = Cproton.pn_messenger_work(@impl, timeout)
|
250
357
|
if (err == Cproton::PN_TIMEOUT) then
|
@@ -269,6 +376,86 @@ module Qpid
|
|
269
376
|
Cproton.pn_messenger_incoming(@impl)
|
270
377
|
end
|
271
378
|
|
379
|
+
# Adds a routing rule to the Messenger's internal routing table.
|
380
|
+
#
|
381
|
+
# The route procedure may be used to influence how a Messenger will
|
382
|
+
# internally treat a given address or class of addresses. Every call
|
383
|
+
# to the route procedure will result in Messenger appending a routing
|
384
|
+
# rule to its internal routing table.
|
385
|
+
#
|
386
|
+
# Whenever a Message is presented to a Messenger for delivery, it
|
387
|
+
# will match the address of this message against the set of routing
|
388
|
+
# rules in order. The first rule to match will be triggered, and
|
389
|
+
# instead of routing based on the address presented in the message,
|
390
|
+
# the Messenger will route based on the address supplied in the rule.
|
391
|
+
#
|
392
|
+
# The pattern matching syntax supports two types of matches, a '%'
|
393
|
+
# will match any character except a '/', and a '*' will match any
|
394
|
+
# character including a '/'.
|
395
|
+
#
|
396
|
+
# A routing address is specified as a normal AMQP address, however it
|
397
|
+
# may additionally use substitution variables from the pattern match
|
398
|
+
# that triggered the rule.
|
399
|
+
#
|
400
|
+
# ==== Arguments
|
401
|
+
#
|
402
|
+
# * pattern - the address pattern
|
403
|
+
# * address - the target address
|
404
|
+
#
|
405
|
+
# ==== Examples
|
406
|
+
#
|
407
|
+
# # route messages sent to foo to the destionaty amqp://foo.com
|
408
|
+
# messenger.route("foo", "amqp://foo.com")
|
409
|
+
#
|
410
|
+
# # any message to foobar will be routed to amqp://foo.com/bar
|
411
|
+
# messenger.route("foobar", "amqp://foo.com/bar")
|
412
|
+
#
|
413
|
+
# # any message to bar/<path> will be routed to the same path within
|
414
|
+
# # the amqp://bar.com domain
|
415
|
+
# messenger.route("bar/*", "amqp://bar.com/$1")
|
416
|
+
#
|
417
|
+
# # route all Message objects over TLS
|
418
|
+
# messenger.route("amqp:*", "amqps:$1")
|
419
|
+
#
|
420
|
+
# # supply credentials for foo
|
421
|
+
# messenger.route("amqp://foo.com/*", "amqp://user:password@foo.com/$1")
|
422
|
+
#
|
423
|
+
# # supply credentials for all domains
|
424
|
+
# messenger.route("amqp://*", "amqp://user:password@$1")
|
425
|
+
#
|
426
|
+
# # route all addresses through a single proxy while preserving the
|
427
|
+
# # original destination
|
428
|
+
# messenger.route("amqp://%$/*", "amqp://user:password@proxy/$1/$2")
|
429
|
+
#
|
430
|
+
# # route any address through a single broker
|
431
|
+
# messenger.route("*", "amqp://user:password@broker/$1")
|
432
|
+
#
|
433
|
+
def route(pattern, address)
|
434
|
+
check_for_error(Cproton.pn_messenger_route(@impl, pattern, address))
|
435
|
+
end
|
436
|
+
|
437
|
+
# Similar to #route, except that the destination of
|
438
|
+
# the Message is determined before the message address is rewritten.
|
439
|
+
#
|
440
|
+
# The outgoing address is only rewritten after routing has been
|
441
|
+
# finalized. If a message has an outgoing address of
|
442
|
+
# "amqp://0.0.0.0:5678", and a rewriting rule that changes its
|
443
|
+
# outgoing address to "foo", it will still arrive at the peer that
|
444
|
+
# is listening on "amqp://0.0.0.0:5678", but when it arrives there,
|
445
|
+
# the receiver will see its outgoing address as "foo".
|
446
|
+
#
|
447
|
+
# The default rewrite rule removes username and password from addresses
|
448
|
+
# before they are transmitted.
|
449
|
+
#
|
450
|
+
# ==== Arguments
|
451
|
+
#
|
452
|
+
# * pattern - the outgoing address
|
453
|
+
# * address - the target address
|
454
|
+
#
|
455
|
+
def rewrite(pattern, address)
|
456
|
+
check_for_error(Cproton.pn_messenger_rewrite(@impl, pattern, address))
|
457
|
+
end
|
458
|
+
|
272
459
|
# Returns a +Tracker+ for the message most recently sent via the put
|
273
460
|
# method.
|
274
461
|
#
|
@@ -286,12 +473,15 @@ module Qpid
|
|
286
473
|
Qpid::Proton::Tracker.new(impl)
|
287
474
|
end
|
288
475
|
|
289
|
-
#
|
476
|
+
# Signal the sender that you have acted on the Message
|
477
|
+
# pointed to by the tracker. If no tracker is supplied,
|
478
|
+
# then all messages that have been returned by the get
|
479
|
+
# method are accepted, except those that have already been
|
480
|
+
# auto-settled by passing beyond your incoming window size.
|
290
481
|
#
|
291
482
|
# ==== Options
|
292
483
|
#
|
293
484
|
# * tracker - the tracker
|
294
|
-
# * flag - the flag
|
295
485
|
#
|
296
486
|
def accept(tracker = nil)
|
297
487
|
raise TypeError.new("invalid tracker: #{tracker}") unless tracker.nil? or valid_tracker?(tracker)
|
@@ -305,11 +495,13 @@ module Qpid
|
|
305
495
|
end
|
306
496
|
|
307
497
|
# Rejects the incoming message identified by the tracker.
|
498
|
+
# If no tracker is supplied, all messages that have been returned
|
499
|
+
# by the get method are rejected, except those that have already
|
500
|
+
# been auto-settled by passing beyond your outgoing window size.
|
308
501
|
#
|
309
502
|
# ==== Options
|
310
503
|
#
|
311
504
|
# * tracker - the tracker
|
312
|
-
# * flag - the flag
|
313
505
|
#
|
314
506
|
def reject(tracker)
|
315
507
|
raise TypeError.new("invalid tracker: #{tracker}") unless tracker.nil? or valid_tracker?(tracker)
|
@@ -323,8 +515,10 @@ module Qpid
|
|
323
515
|
end
|
324
516
|
|
325
517
|
# Gets the last known remote state of the delivery associated with
|
326
|
-
# the given tracker
|
327
|
-
#
|
518
|
+
# the given tracker, as long as the Message is still within your
|
519
|
+
# outgoing window. (Also works on incoming messages that are still
|
520
|
+
# within your incoming queue. See TrackerStatus for details on the
|
521
|
+
# values returned.
|
328
522
|
#
|
329
523
|
# ==== Options
|
330
524
|
#
|
@@ -335,26 +529,37 @@ module Qpid
|
|
335
529
|
Qpid::Proton::TrackerStatus.by_value(Cproton.pn_messenger_status(@impl, tracker.impl))
|
336
530
|
end
|
337
531
|
|
338
|
-
#
|
532
|
+
# Frees a Messenger from tracking the status associated
|
533
|
+
# with a given tracker. If you don't supply a tracker, all
|
534
|
+
# outgoing messages up to the most recent will be settled.
|
339
535
|
#
|
340
536
|
# ==== Options
|
341
537
|
#
|
342
538
|
# * tracker - the tracker
|
343
|
-
# * flag - the flag
|
344
539
|
#
|
345
540
|
# ==== Examples
|
346
541
|
#
|
347
|
-
def settle(tracker
|
542
|
+
def settle(tracker)
|
348
543
|
raise TypeError.new("invalid tracker: #{tracker}") unless valid_tracker?(tracker)
|
349
|
-
|
544
|
+
if tracker.nil? then
|
545
|
+
tracker = self.incoming_tracker
|
546
|
+
flag = Cproton::PN_CUMULATIVE
|
547
|
+
else
|
548
|
+
flag = 0
|
549
|
+
end
|
350
550
|
Cproton.pn_messenger_settle(@impl, tracker.impl, flag)
|
351
551
|
end
|
352
552
|
|
353
553
|
# Sets the incoming window.
|
354
554
|
#
|
355
|
-
#
|
356
|
-
#
|
357
|
-
#
|
555
|
+
# The Messenger will track the remote status of this many incoming
|
556
|
+
# deliveries after they have been accepted or rejected.
|
557
|
+
#
|
558
|
+
# Messages enter this window only when you take them into your application
|
559
|
+
# using get(). If your incoming window size is n, and you get n+1 messages
|
560
|
+
# without explicitly accepting or rejecting the oldest message, then the
|
561
|
+
# message that passes beyond the edge of the incoming window will be
|
562
|
+
# assigned the default disposition of its link.
|
358
563
|
#
|
359
564
|
# ==== Options
|
360
565
|
#
|
@@ -371,10 +576,14 @@ module Qpid
|
|
371
576
|
Cproton.pn_messenger_get_incoming_window(@impl)
|
372
577
|
end
|
373
578
|
|
374
|
-
#Sets the outgoing window.
|
579
|
+
# Sets the outgoing window.
|
375
580
|
#
|
376
|
-
#
|
377
|
-
#
|
581
|
+
# The Messenger will track the remote status of this many outgoing
|
582
|
+
# deliveries after calling send.
|
583
|
+
# A Message enters this window when you call the put() method with the
|
584
|
+
# message. If your outgoing window size is n, and you call put n+1
|
585
|
+
# times, status information will no longer be available for the
|
586
|
+
# first message.
|
378
587
|
#
|
379
588
|
# ==== Options
|
380
589
|
#
|