qpid_proton 0.5 → 0.6

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