qpid_proton 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
#
|