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.
@@ -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
- # A +Messenger+ provides a high-level means for sending and
25
- # receiving AMQP messages.
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
- # ==== Examples
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
- # Starts the +Messenger+, allowing it to begin sending and
105
- # receiving messages.
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 +Messenger+ to a remote address.
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
- # Puts a single message into the outgoing queue.
256
+ # Places the content contained in the message onto the outgoing
257
+ # queue of the Messenger.
189
258
  #
190
- # To ensure messages are sent, you should then call ::send.
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
- # Sends all outgoing messages, blocking until the outgoing queue
206
- # is empty.
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
- # Gets a single message incoming message from the local queue.
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 the specified number of messages, blocking until at least
234
- # one message is received.
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
- # Accepts the incoming message identified by the tracker.
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. See TrackerStatus for details on the values
327
- # returned.
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
- # Settles messages for a tracker.
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, flag)
542
+ def settle(tracker)
348
543
  raise TypeError.new("invalid tracker: #{tracker}") unless valid_tracker?(tracker)
349
- raise TypeError.new("invalid flag: #{flag}") unless Qpid::Proton::Tracker.valid_flag?(flag)
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
- # If the incoming window is set to a positive value, then after each
356
- # call to #accept or #reject, the object will track the status of that
357
- # many deliveries.
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
- # If the outgoing window is set to a positive value, then after each call
377
- # to #send, the object will track the status of that many deliveries.
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
  #