1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """
21 The proton module defines a suite of APIs that implement the AMQP 1.0
22 protocol.
23
24 The proton APIs consist of the following classes:
25
26 - L{Messenger} -- A messaging endpoint.
27 - L{Message} -- A class for creating and/or accessing AMQP message content.
28 - L{Data} -- A class for creating and/or accessing arbitrary AMQP encoded
29 data.
30
31 """
32
33 from cproton import *
34 import uuid
35
36 LANGUAGE = "C"
45
47 """
48 The root of the proton exception hierarchy. All proton exception
49 classes derive from this exception.
50 """
51 pass
52
54 """
55 A timeout exception indicates that a blocking operation has timed
56 out.
57 """
58 pass
59
61 """
62 The root of the messenger exception hierarchy. All exceptions
63 generated by the messenger class derive from this exception.
64 """
65 pass
66
68 """
69 The MessageException class is the root of the message exception
70 hierarhcy. All exceptions generated by the Message class derive from
71 this exception.
72 """
73 pass
74
75 EXCEPTIONS = {
76 PN_TIMEOUT: Timeout
77 }
78
79 PENDING = Constant("PENDING")
80 ACCEPTED = Constant("ACCEPTED")
81 REJECTED = Constant("REJECTED")
82
83 STATUSES = {
84 PN_STATUS_ACCEPTED: ACCEPTED,
85 PN_STATUS_REJECTED: REJECTED,
86 PN_STATUS_PENDING: PENDING,
87 PN_STATUS_UNKNOWN: None
88 }
89
90 AUTOMATIC = Constant("AUTOMATIC")
91 MANUAL = Constant("MANUAL")
94 """
95 The L{Messenger} class defines a high level interface for sending
96 and receiving L{Messages<Message>}. Every L{Messenger} contains a
97 single logical queue of incoming messages and a single logical queue
98 of outgoing messages. These messages in these queues may be destined
99 for, or originate from, a variety of addresses.
100
101 Address Syntax
102 ==============
103
104 An address has the following form::
105
106 [ amqp[s]:// ] [user[:password]@] domain [/[name]]
107
108 Where domain can be one of::
109
110 host | host:port | ip | ip:port | name
111
112 The following are valid examples of addresses:
113
114 - example.org
115 - example.org:1234
116 - amqp://example.org
117 - amqps://example.org
118 - example.org/incoming
119 - amqps://example.org/outgoing
120 - amqps://fred:trustno1@example.org
121 - 127.0.0.1:1234
122 - amqps://127.0.0.1:1234
123
124 Sending & Receiving Messages
125 ============================
126
127 The L{Messenger} class works in conjuction with the L{Message}
128 class. The L{Message} class is a mutable holder of message content.
129 The L{put} method will encode the content in a given L{Message}
130 object into the outgoing message queue leaving that L{Message}
131 object free to be modified or discarded without having any impact on
132 the content in the outgoing queue.
133
134 >>> message = Message()
135 >>> for i in range(3):
136 ... message.address = "amqp://host/queue"
137 ... message.subject = "Hello World %i" % i
138 ... messenger.put(message)
139 >>> messenger.send()
140
141 Similarly, the L{get} method will decode the content in the incoming
142 message queue into the supplied L{Message} object.
143
144 >>> message = Message()
145 >>> messenger.recv(10):
146 >>> while messenger.incoming > 0:
147 ... messenger.get(message)
148 ... print message.subject
149 Hello World 0
150 Hello World 1
151 Hello World 2
152 """
153
155 """
156 Construct a new L{Messenger} with the given name. The name has
157 global scope. If a NULL name is supplied, a L{uuid.UUID} based
158 name will be chosen.
159
160 @type name: string
161 @param name: the name of the messenger or None
162 """
163 self._mng = pn_messenger(name)
164
166 if hasattr(self, "_mng"):
167 pn_messenger_free(self._mng)
168 del self._mng
169
171 if err < 0:
172 exc = EXCEPTIONS.get(err, MessengerException)
173 raise exc("[%s]: %s" % (err, pn_messenger_error(self._mng)))
174 else:
175 return err
176
177 @property
179 """
180 The name of the L{Messenger}.
181 """
182 return pn_messenger_name(self._mng)
183
185 return pn_messenger_get_certificate(self._mng)
186
188 self._check(pn_messenger_set_certificate(self._mng, value))
189
190 certificate = property(_get_certificate, _set_certificate,
191 doc="""
192 Path to a certificate file for the L{Messenger}. This certificate is
193 used when the L{Messenger} accepts or establishes SSL/TLS connections.
194 This property must be specified for the L{Messenger} to accept
195 incoming SSL/TLS connections and to establish client authenticated
196 outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS
197 connections do not require this property.
198 """)
199
201 return pn_messenger_get_private_key(self._mng)
202
204 self._check(pn_messenger_set_private_key(self._mng, value))
205
206 private_key = property(_get_private_key, _set_private_key,
207 doc="""
208 Path to a private key file for the L{Messenger's<Messenger>}
209 certificate. This property must be specified for the L{Messenger} to
210 accept incoming SSL/TLS connections and to establish client
211 authenticated outgoing SSL/TLS connection. Non client authenticated
212 SSL/TLS connections do not require this property.
213 """)
214
216 return pn_messenger_get_password(self._mng)
217
219 self._check(pn_messenger_set_password(self._mng, value))
220
221 password = property(_get_password, _set_password,
222 doc="""
223 This property contains the password for the L{Messenger.private_key}
224 file, or None if the file is not encrypted.
225 """)
226
228 return pn_messenger_get_trusted_certificates(self._mng)
229
231 self._check(pn_messenger_set_trusted_certificates(self._mng, value))
232
233 trusted_certificates = property(_get_trusted_certificates,
234 _set_trusted_certificates,
235 doc="""
236 A path do a database of trusted certificates for use in verifying the
237 peer on an SSL/TLS connection. If this property is None, then the peer
238 will not be verified.
239 """)
240
242 return pn_messenger_get_timeout(self._mng)
243
245 self._check(pn_messenger_set_timeout(self._mng, value))
246
247 timeout = property(_get_timeout, _set_timeout,
248 doc="""
249 The timeout property contains the default timeout for blocking
250 operations performed by the L{Messenger}.
251 """)
252
254 return pn_messenger_get_incoming_window(self._mng)
255
257 self._check(pn_messenger_set_incoming_window(self._mng, window))
258
259 incoming_window = property(_get_incoming_window, _set_incoming_window,
260 doc="""
261 The incoming tracking window for the messenger. The messenger will
262 track the remote status of this many incoming deliveries after they
263 have been accepted or rejected. Defaults to zero.
264 """)
265
267 return pn_messenger_get_outgoing_window(self._mng)
268
270 self._check(pn_messenger_set_outgoing_window(self._mng, window))
271
272 outgoing_window = property(_get_outgoing_window, _set_outgoing_window,
273 doc="""
274 The outgoing tracking window for the messenger. The messenger will
275 track the remote status of this many outgoing deliveries after calling
276 send. Defaults to zero.
277 """)
278
280 """
281 Transitions the L{Messenger} to an active state. A L{Messenger} is
282 initially created in an inactive state. When inactive a
283 L{Messenger} will not send or receive messages from its internal
284 queues. A L{Messenger} must be started before calling L{send} or
285 L{recv}.
286 """
287 self._check(pn_messenger_start(self._mng))
288
290 """
291 Transitions the L{Messenger} to an inactive state. An inactive
292 L{Messenger} will not send or receive messages from its internal
293 queues. A L{Messenger} should be stopped before being discarded to
294 ensure a clean shutdown handshake occurs on any internally managed
295 connections.
296 """
297 self._check(pn_messenger_stop(self._mng))
298
300 """
301 Subscribes the L{Messenger} to messages originating from the
302 specified source. The source is an address as specified in the
303 L{Messenger} introduction with the following addition. If the
304 domain portion of the address begins with the '~' character, the
305 L{Messenger} will interpret the domain as host/port, bind to it,
306 and listen for incoming messages. For example "~0.0.0.0",
307 "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any
308 local interface and listen for incoming messages with the last
309 variant only permitting incoming SSL connections.
310
311 @type source: string
312 @param source: the source of messages to subscribe to
313 """
314 sub_impl = pn_messenger_subscribe(self._mng, source)
315 if not sub_impl:
316 self._check(PN_ERR)
317
318 - def put(self, message):
319 """
320 Places the content contained in the message onto the outgoing
321 queue of the L{Messenger}. This method will never block, however
322 it will send any unblocked L{Messages<Message>} in the outgoing
323 queue immediately and leave any blocked L{Messages<Message>}
324 remaining in the outgoing queue. The L{send} call may be used to
325 block until the outgoing queue is empty. The L{outgoing} property
326 may be used to check the depth of the outgoing queue.
327
328 @type message: Message
329 @param message: the message to place in the outgoing queue
330 @return: a tracker
331 """
332 message._pre_encode()
333 self._check(pn_messenger_put(self._mng, message._msg))
334 return pn_messenger_outgoing_tracker(self._mng)
335
337 """
338 Gets the last known remote state of the delivery associated with
339 the given tracker.
340
341 @type tracker: tracker
342 @param tracker: the tracker whose status is to be retrieved
343
344 @return: one of None, PENDING, REJECTED, or ACCEPTED
345 """
346 disp = pn_messenger_status(self._mng, tracker);
347 return STATUSES.get(disp, disp)
348
349 - def settle(self, tracker=None):
350 if tracker is None:
351 tracker = pn_messenger_outgoing_tracker(self._mng)
352 flags = PN_CUMULATIVE
353 else:
354 flags = 0
355 self._check(pn_messenger_settle(self._mng, tracker, flags))
356
358 """
359 Blocks until the outgoing queue is empty or the operation times
360 out. The L{timeout} property controls how long a L{Messenger} will
361 block before timing out.
362 """
363 self._check(pn_messenger_send(self._mng))
364
366 """
367 Receives up to I{n} messages into the incoming queue of the
368 L{Messenger}. This method will block until at least one message is
369 available or the operation times out.
370 """
371 self._check(pn_messenger_recv(self._mng, n))
372
373 - def get(self, message=None):
374 """
375 Moves the message from the head of the incoming message queue into
376 the supplied message object. Any content in the message will be
377 overwritten.
378
379 @type message: Message
380 @param message: the destination message object
381 @return: a tracker
382 """
383 if message is None:
384 impl = None
385 else:
386 impl = message._msg
387 self._check(pn_messenger_get(self._mng, impl))
388 if message is not None:
389 message._post_decode()
390 return pn_messenger_incoming_tracker(self._mng)
391
392 - def accept(self, tracker=None):
393 """
394 Accepts messages retreived from the incoming message queue.
395
396 @type tracker: tracker
397 @param tracker: a tracker as returned by get
398 """
399 if tracker is None:
400 tracker = pn_messenger_incoming_tracker(self._mng)
401 flags = PN_CUMULATIVE
402 else:
403 flags = 0
404 self._check(pn_messenger_accept(self._mng, tracker, flags))
405
406 - def reject(self, tracker=None):
407 """
408 Rejects messages retreived from the incoming message queue.
409
410 @type tracker: tracker
411 @param tracker: a tracker as returned by get
412 """
413 if tracker is None:
414 tracker = pn_messenger_incoming_tracker(self._mng)
415 flags = PN_CUMULATIVE
416 else:
417 flags = 0
418 self._check(pn_messenger_reject(self._mng, tracker, flags))
419
420 @property
422 """
423 The outgoing queue depth.
424 """
425 return pn_messenger_outgoing(self._mng)
426
427 @property
429 """
430 The incoming queue depth.
431 """
432 return pn_messenger_incoming(self._mng)
433
435 """
436 The L{Message} class is a mutable holder of message content.
437
438 @ivar instructions: delivery instructions for the message
439 @type instructions: dict
440 @ivar annotations: infrastructure defined message annotations
441 @type annotations: dict
442 @ivar properties: application defined message properties
443 @type properties: dict
444 @ivar body: message body
445 @type body: bytes | unicode | dict | list | int | long | float | UUID
446 """
447
448 DATA = PN_DATA
449 TEXT = PN_TEXT
450 AMQP = PN_AMQP
451 JSON = PN_JSON
452
453 DEFAULT_PRIORITY = PN_DEFAULT_PRIORITY
454
456 self._msg = pn_message()
457 self._id = Data(pn_message_id(self._msg))
458 self._correlation_id = Data(pn_message_correlation_id(self._msg))
459 self.instructions = None
460 self.annotations = None
461 self.properties = None
462 self.body = None
463
465 if hasattr(self, "_msg"):
466 pn_message_free(self._msg)
467 del self._msg
468
470 if err < 0:
471 exc = EXCEPTIONS.get(err, MessageException)
472 raise exc("[%s]: %s" % (err, pn_message_error(self._msg)))
473 else:
474 return err
475
477 inst = Data(pn_message_instructions(self._msg))
478 ann = Data(pn_message_annotations(self._msg))
479 props = Data(pn_message_properties(self._msg))
480 body = Data(pn_message_body(self._msg))
481
482 inst.clear()
483 if self.instructions is not None:
484 inst.put_object(self.instructions)
485 ann.clear()
486 if self.annotations is not None:
487 ann.put_object(self.annotations)
488 props.clear()
489 if self.properties is not None:
490 props.put_object(self.properties)
491 if self.body is not None:
492
493 body.clear()
494 body.put_object(self.body)
495
496 - def _post_decode(self):
497 inst = Data(pn_message_instructions(self._msg))
498 ann = Data(pn_message_annotations(self._msg))
499 props = Data(pn_message_properties(self._msg))
500 body = Data(pn_message_body(self._msg))
501
502 if inst.next():
503 self.instructions = inst.get_object()
504 else:
505 self.instructions = None
506 if ann.next():
507 self.annotations = ann.get_object()
508 else:
509 self.annotations = None
510 if props.next():
511 self.properties = props.get_object()
512 else:
513 self.properties = None
514 if body.next():
515 self.body = body.get_object()
516 else:
517 self.body = None
518
520 """
521 Clears the contents of the L{Message}. All fields will be reset to
522 their default values.
523 """
524 pn_message_clear(self._msg)
525 self.instructions = None
526 self.annotations = None
527 self.properties = None
528 self.body = None
529
531 return pn_message_is_inferred(self._msg)
532
534 self._check(pn_message_set_inferred(self._msg, bool(value)))
535
536 inferred = property(_is_inferred, _set_inferred)
537
539 return pn_message_is_durable(self._msg)
540
542 self._check(pn_message_set_durable(self._msg, bool(value)))
543
544 durable = property(_is_durable, _set_durable,
545 doc="""
546 The durable property indicates that the message should be held durably
547 by any intermediaries taking responsibility for the message.
548 """)
549
551 return pn_message_get_priority(self._msg)
552
554 self._check(pn_message_set_priority(self._msg, value))
555
556 priority = property(_get_priority, _set_priority,
557 doc="""
558 The priority of the message.
559 """)
560
562 return pn_message_get_ttl(self._msg)
563
565 self._check(pn_message_set_ttl(self._msg, value))
566
567 ttl = property(_get_ttl, _set_ttl,
568 doc="""
569 The time to live of the message measured in milliseconds. Expired
570 messages may be dropped.
571 """)
572
574 return pn_message_is_first_acquirer(self._msg)
575
577 self._check(pn_message_set_first_acquirer(self._msg, bool(value)))
578
579 first_acquirer = property(_is_first_acquirer, _set_first_acquirer,
580 doc="""
581 True iff the recipient is the first to acquire the message.
582 """)
583
585 return pn_message_get_delivery_count(self._msg)
586
588 self._check(pn_message_set_delivery_count(self._msg, value))
589
590 delivery_count = property(_get_delivery_count, _set_delivery_count,
591 doc="""
592 The number of delivery attempts made for this message.
593 """)
594
595
603 id = property(_get_id, _set_id,
604 doc="""
605 The id of the message.
606 """)
607
609 return pn_message_get_user_id(self._msg)
610
612 self._check(pn_message_set_user_id(self._msg, value))
613
614 user_id = property(_get_user_id, _set_user_id,
615 doc="""
616 The user id of the message creator.
617 """)
618
620 return pn_message_get_address(self._msg)
621
623 self._check(pn_message_set_address(self._msg, value))
624
625 address = property(_get_address, _set_address,
626 doc="""
627 The address of the message.
628 """)
629
631 return pn_message_get_subject(self._msg)
632
634 self._check(pn_message_set_subject(self._msg, value))
635
636 subject = property(_get_subject, _set_subject,
637 doc="""
638 The subject of the message.
639 """)
640
642 return pn_message_get_reply_to(self._msg)
643
645 self._check(pn_message_set_reply_to(self._msg, value))
646
647 reply_to = property(_get_reply_to, _set_reply_to,
648 doc="""
649 The reply-to address for the message.
650 """)
651
655 if type(value) in (int, long):
656 value = ulong(value)
657 self._correlation_id.rewind()
658 self._correlation_id.put_object(value)
659
660 correlation_id = property(_get_correlation_id, _set_correlation_id,
661 doc="""
662 The correlation-id for the message.
663 """)
664
666 return pn_message_get_content_type(self._msg)
667
668 - def _set_content_type(self, value):
669 self._check(pn_message_set_content_type(self._msg, value))
670
671 content_type = property(_get_content_type, _set_content_type,
672 doc="""
673 The content-type of the message.
674 """)
675
677 return pn_message_get_content_encoding(self._msg)
678
679 - def _set_content_encoding(self, value):
680 self._check(pn_message_set_content_encoding(self._msg, value))
681
682 content_encoding = property(_get_content_encoding, _set_content_encoding,
683 doc="""
684 The content-encoding of the message.
685 """)
686
688 return pn_message_get_expiry_time(self._msg)
689
691 self._check(pn_message_set_expiry_time(self._msg, value))
692
693 expiry_time = property(_get_expiry_time, _set_expiry_time,
694 doc="""
695 The expiry time of the message.
696 """)
697
699 return pn_message_get_creation_time(self._msg)
700
702 self._check(pn_message_set_creation_time(self._msg, value))
703
704 creation_time = property(_get_creation_time, _set_creation_time,
705 doc="""
706 The creation time of the message.
707 """)
708
710 return pn_message_get_group_id(self._msg)
711
713 self._check(pn_message_set_group_id(self._msg, value))
714
715 group_id = property(_get_group_id, _set_group_id,
716 doc="""
717 The group id of the message.
718 """)
719
721 return pn_message_get_group_sequence(self._msg)
722
724 self._check(pn_message_set_group_sequence(self._msg, value))
725
726 group_sequence = property(_get_group_sequence, _set_group_sequence,
727 doc="""
728 The sequence of the message within its group.
729 """)
730
732 return pn_message_get_reply_to_group_id(self._msg)
733
735 self._check(pn_message_set_reply_to_group_id(self._msg, value))
736
737 reply_to_group_id = property(_get_reply_to_group_id, _set_reply_to_group_id,
738 doc="""
739 The group-id for any replies.
740 """)
741
742
745
748
749 format = property(_get_format, _set_format,
750 doc="""
751 The format of the message.
752 """)
753
755 self._pre_encode()
756 sz = 16
757 while True:
758 err, data = pn_message_encode(self._msg, sz)
759 if err == PN_OVERFLOW:
760 sz *= 2
761 continue
762 else:
763 self._check(err)
764 return data
765
767 self._check(pn_message_decode(self._msg, data, len(data)))
768 self._post_decode()
769
770 - def load(self, data):
771 self._check(pn_message_load(self._msg, data))
772
774 sz = 16
775 while True:
776 err, data = pn_message_save(self._msg, sz)
777 if err == PN_OVERFLOW:
778 sz *= 2
779 continue
780 else:
781 self._check(err)
782 return data
783
785 """
786 The DataException class is the root of the Data exception hierarchy.
787 All exceptions raised by the Data class extend this exception.
788 """
789 pass
790
792
795
797 return "UnmappedType(%s)" % self.msg
798
800
802 return "ulong(%s)" % long.__repr__(self)
803
805
807 return "timestamp(%s)" % long.__repr__(self)
808
810
812 return "symbol(%s)" % unicode.__repr__(self)
813
814 -class char(unicode):
815
817 return "char(%s)" % unicode.__repr__(self)
818
820
822 self.descriptor = descriptor
823 self.value = value
824
826 return "Described(%r, %r)" % (self.descriptor, self.value)
827
829 if isinstance(o, Described):
830 return self.descriptor == o.descriptor and self.value == o.value
831 else:
832 return False
833
834 UNDESCRIBED = Constant("UNDESCRIBED")
837
838 - def __init__(self, descriptor, type, *elements):
839 self.descriptor = descriptor
840 self.type = type
841 self.elements = elements
842
844 if self.elements:
845 els = ", %s" % (", ".join(map(repr, self.elements)))
846 else:
847 els = ""
848 return "Array(%r, %r%s)" % (self.descriptor, self.type, els)
849
851 if isinstance(o, Array):
852 return self.descriptor == o.descriptor and \
853 self.type == o.type and self.elements == o.elements
854 else:
855 return False
856
858 """
859 The L{Data} class provides an interface for decoding, extracting,
860 creating, and encoding arbitrary AMQP data. A L{Data} object
861 contains a tree of AMQP values. Leaf nodes in this tree correspond
862 to scalars in the AMQP type system such as L{ints<INT>} or
863 L{strings<STRING>}. Non-leaf nodes in this tree correspond to
864 compound values in the AMQP type system such as L{lists<LIST>},
865 L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.
866 The root node of the tree is the L{Data} object itself and can have
867 an arbitrary number of children.
868
869 A L{Data} object maintains the notion of the current sibling node
870 and a current parent node. Siblings are ordered within their parent.
871 Values are accessed and/or added by using the L{next}, L{prev},
872 L{enter}, and L{exit} methods to navigate to the desired location in
873 the tree and using the supplied variety of put_*/get_* methods to
874 access or add a value of the desired type.
875
876 The put_* methods will always add a value I{after} the current node
877 in the tree. If the current node has a next sibling the put_* method
878 will overwrite the value on this node. If there is no current node
879 or the current node has no next sibling then one will be added. The
880 put_* methods always set the added/modified node to the current
881 node. The get_* methods read the value of the current node and do
882 not change which node is current.
883
884 The following types of scalar values are supported:
885
886 - L{NULL}
887 - L{BOOL}
888 - L{UBYTE}
889 - L{USHORT}
890 - L{SHORT}
891 - L{UINT}
892 - L{INT}
893 - L{ULONG}
894 - L{LONG}
895 - L{FLOAT}
896 - L{DOUBLE}
897 - L{BINARY}
898 - L{STRING}
899 - L{SYMBOL}
900
901 The following types of compound values are supported:
902
903 - L{DESCRIBED}
904 - L{ARRAY}
905 - L{LIST}
906 - L{MAP}
907 """
908
909 NULL = PN_NULL; "A null value."
910 BOOL = PN_BOOL; "A boolean value."
911 UBYTE = PN_UBYTE; "An unsigned byte value."
912 BYTE = PN_BYTE; "A signed byte value."
913 USHORT = PN_USHORT; "An unsigned short value."
914 SHORT = PN_SHORT; "A short value."
915 UINT = PN_UINT; "An unsigned int value."
916 INT = PN_INT; "A signed int value."
917 CHAR = PN_CHAR; "A character value."
918 ULONG = PN_ULONG; "An unsigned long value."
919 LONG = PN_LONG; "A signed long value."
920 TIMESTAMP = PN_TIMESTAMP; "A timestamp value."
921 FLOAT = PN_FLOAT; "A float value."
922 DOUBLE = PN_DOUBLE; "A double value."
923 DECIMAL32 = PN_DECIMAL32; "A DECIMAL32 value."
924 DECIMAL64 = PN_DECIMAL64; "A DECIMAL64 value."
925 DECIMAL128 = PN_DECIMAL128; "A DECIMAL128 value."
926 UUID = PN_UUID; "A UUID value."
927 BINARY = PN_BINARY; "A binary string."
928 STRING = PN_STRING; "A unicode string."
929 SYMBOL = PN_SYMBOL; "A symbolic string."
930 DESCRIBED = PN_DESCRIBED; "A described value."
931 ARRAY = PN_ARRAY; "An array value."
932 LIST = PN_LIST; "A list value."
933 MAP = PN_MAP; "A map value."
934
936 if type(capacity) in (int, long):
937 self._data = pn_data(capacity)
938 self._free = True
939 else:
940 self._data = capacity
941 self._free = False
942
944 if self._free and hasattr(self, "_data"):
945 pn_data_free(self._data)
946 del self._data
947
949 if err < 0:
950 exc = EXCEPTIONS.get(err, DataException)
951 raise exc("[%s]: %s" % (err, pn_data_error(self._data)))
952 else:
953 return err
954
956 """
957 Clears the data object.
958 """
959 pn_data_clear(self._data)
960
962 """
963 Clears current node and sets the parent to the root node.
964 """
965 pn_data_rewind(self._data)
966
968 """
969 Advances the current node to its next sibling and returns its
970 type. If there is no next sibling the current node remains
971 unchanged and None is returned.
972 """
973 found = pn_data_next(self._data)
974 if found:
975 return self.type()
976 else:
977 return None
978
980 """
981 Advances the current node to its previous sibling and returns its
982 type. If there is no previous sibling the current node remains
983 unchanged and None is returned.
984 """
985 found = pn_data_prev(self._data)
986 if found:
987 return self.type()
988 else:
989 return None
990
992 """
993 Sets the parent node to the current node and clears the current node.
994 """
995 return pn_data_enter(self._data)
996
998 """
999 Sets the current node to the parent node and the parent node to
1000 its own parent.
1001 """
1002 return pn_data_exit(self._data)
1003
1005 """
1006 Returns the type of the current node.
1007 """
1008 dtype = pn_data_type(self._data)
1009 if dtype == -1:
1010 return None
1011 else:
1012 return dtype
1013
1015 """
1016 Returns a representation of the data encoded in AMQP format.
1017 """
1018 size = 1024
1019 while True:
1020 cd, enc = pn_data_encode(self._data, size)
1021 if cd == PN_OVERFLOW:
1022 size *= 2
1023 elif cd >= 0:
1024 return enc
1025 else:
1026 self._check(cd)
1027
1029 """
1030 Decodes the first value from supplied AMQP data and returns the
1031 number of bytes consumed.
1032
1033 @type encoded: binary
1034 @param encoded: AMQP encoded binary data
1035 """
1036 return self._check(pn_data_decode(self._data, encoded))
1037
1039 """
1040 Puts a list value. Elements may be filled by entering the list
1041 node and putting element values.
1042
1043 >>> data = Data()
1044 >>> data.put_list()
1045 >>> data.enter()
1046 >>> data.put_int(1)
1047 >>> data.put_int(2)
1048 >>> data.put_int(3)
1049 >>> data.exit()
1050 """
1051 self._check(pn_data_put_list(self._data))
1052
1054 """
1055 Puts a map value. Elements may be filled by entering the map node
1056 and putting alternating key value pairs.
1057
1058 >>> data = Data()
1059 >>> data.put_map()
1060 >>> data.enter()
1061 >>> data.put_string("key")
1062 >>> data.put_string("value")
1063 >>> data.exit()
1064 """
1065 self._check(pn_data_put_map(self._data))
1066
1067 - def put_array(self, described, element_type):
1068 """
1069 Puts an array value. Elements may be filled by entering the array
1070 node and putting the element values. The values must all be of the
1071 specified array element type. If an array is described then the
1072 first child value of the array is the descriptor and may be of any
1073 type.
1074
1075 >>> data = Data()
1076 >>>
1077 >>> data.put_array(False, Data.INT)
1078 >>> data.enter()
1079 >>> data.put_int(1)
1080 >>> data.put_int(2)
1081 >>> data.put_int(3)
1082 >>> data.exit()
1083 >>>
1084 >>> data.put_array(True, Data.DOUBLE)
1085 >>> data.enter()
1086 >>> data.put_symbol("array-descriptor")
1087 >>> data.put_double(1.1)
1088 >>> data.put_double(1.2)
1089 >>> data.put_double(1.3)
1090 >>> data.exit()
1091
1092 @type described: bool
1093 @param described: specifies whether the array is described
1094 @type element_type: int
1095 @param element_type: the type of the array elements
1096 """
1097 self._check(pn_data_put_array(self._data, described, element_type))
1098
1100 """
1101 Puts a described value. A described node has two children, the
1102 descriptor and the value. These are specified by entering the node
1103 and putting the desired values.
1104
1105 >>> data = Data()
1106 >>> data.put_described()
1107 >>> data.enter()
1108 >>> data.put_symbol("value-descriptor")
1109 >>> data.put_string("the value")
1110 >>> data.exit()
1111 """
1112 self._check(pn_data_put_described(self._data))
1113
1115 """
1116 Puts a null value.
1117 """
1118 self._check(pn_data_put_null(self._data))
1119
1121 """
1122 Puts a boolean value.
1123
1124 @param b: a boolean value
1125 """
1126 self._check(pn_data_put_bool(self._data, b))
1127
1129 """
1130 Puts an unsigned byte value.
1131
1132 @param ub: an integral value
1133 """
1134 self._check(pn_data_put_ubyte(self._data, ub))
1135
1137 """
1138 Puts a signed byte value.
1139
1140 @param b: an integral value
1141 """
1142 self._check(pn_data_put_byte(self._data, b))
1143
1145 """
1146 Puts an unsigned short value.
1147
1148 @param us: an integral value.
1149 """
1150 self._check(pn_data_put_ushort(self._data, us))
1151
1153 """
1154 Puts a signed short value.
1155
1156 @param s: an integral value
1157 """
1158 self._check(pn_data_put_short(self._data, s))
1159
1161 """
1162 Puts an unsigned int value.
1163
1164 @param ui: an integral value
1165 """
1166 self._check(pn_data_put_uint(self._data, ui))
1167
1169 """
1170 Puts a signed int value.
1171
1172 @param i: an integral value
1173 """
1174 self._check(pn_data_put_int(self._data, i))
1175
1177 """
1178 Puts a char value.
1179
1180 @param c: a single character
1181 """
1182 self._check(pn_data_put_char(self._data, ord(c)))
1183
1185 """
1186 Puts an unsigned long value.
1187
1188 @param ul: an integral value
1189 """
1190 self._check(pn_data_put_ulong(self._data, ul))
1191
1193 """
1194 Puts a signed long value.
1195
1196 @param l: an integral value
1197 """
1198 self._check(pn_data_put_long(self._data, l))
1199
1201 """
1202 Puts a timestamp value.
1203
1204 @param t: an integral value
1205 """
1206 self._check(pn_data_put_timestamp(self._data, t))
1207
1209 """
1210 Puts a float value.
1211
1212 @param f: a floating point value
1213 """
1214 self._check(pn_data_put_float(self._data, f))
1215
1217 """
1218 Puts a double value.
1219
1220 @param d: a floating point value.
1221 """
1222 self._check(pn_data_put_double(self._data, d))
1223
1225 """
1226 Puts a decimal32 value.
1227
1228 @param d: a decimal32 value
1229 """
1230 self._check(pn_data_put_decimal32(self._data, d))
1231
1233 """
1234 Puts a decimal64 value.
1235
1236 @param d: a decimal64 value
1237 """
1238 self._check(pn_data_put_decimal64(self._data, d))
1239
1241 """
1242 Puts a decimal128 value.
1243
1244 @param d: a decimal128 value
1245 """
1246 self._check(pn_data_put_decimal128(self._data, d))
1247
1249 """
1250 Puts a UUID value.
1251
1252 @param u: a uuid value
1253 """
1254 self._check(pn_data_put_uuid(self._data, u.bytes))
1255
1257 """
1258 Puts a binary value.
1259
1260 @type b: binary
1261 @param b: a binary value
1262 """
1263 self._check(pn_data_put_binary(self._data, b))
1264
1266 """
1267 Puts a unicode value.
1268
1269 @type s: unicode
1270 @param s: a unicode value
1271 """
1272 self._check(pn_data_put_string(self._data, s.encode("utf8")))
1273
1275 """
1276 Puts a symbolic value.
1277
1278 @type s: string
1279 @param s: the symbol name
1280 """
1281 self._check(pn_data_put_symbol(self._data, s))
1282
1284 """
1285 If the current node is a list, return the number of elements,
1286 otherwise return zero. List elements can be accessed by entering
1287 the list.
1288
1289 >>> count = data.get_list()
1290 >>> data.enter()
1291 >>> for i in range(count):
1292 ... type = data.next()
1293 ... if type == Data.STRING:
1294 ... print data.get_string()
1295 ... elif type == ...:
1296 ... ...
1297 >>> data.exit()
1298 """
1299 return pn_data_get_list(self._data)
1300
1302 """
1303 If the current node is a map, return the number of child elements,
1304 otherwise return zero. Key value pairs can be accessed by entering
1305 the map.
1306
1307 >>> count = data.get_map()
1308 >>> data.enter()
1309 >>> for i in range(count/2):
1310 ... type = data.next()
1311 ... if type == Data.STRING:
1312 ... print data.get_string()
1313 ... elif type == ...:
1314 ... ...
1315 >>> data.exit()
1316 """
1317 return pn_data_get_map(self._data)
1318
1320 """
1321 If the current node is an array, return a tuple of the element
1322 count, a boolean indicating whether the array is described, and
1323 the type of each element, otherwise return (0, False, None). Array
1324 data can be accessed by entering the array.
1325
1326 >>> # read an array of strings with a symbolic descriptor
1327 >>> count, described, type = data.get_array()
1328 >>> data.enter()
1329 >>> data.next()
1330 >>> print "Descriptor:", data.get_symbol()
1331 >>> for i in range(count):
1332 ... data.next()
1333 ... print "Element:", data.get_string()
1334 >>> data.exit()
1335 """
1336 count = pn_data_get_array(self._data)
1337 described = pn_data_is_array_described(self._data)
1338 type = pn_data_get_array_type(self._data)
1339 if type == -1:
1340 type = None
1341 return count, described, type
1342
1344 """
1345 Checks if the current node is a described value. The descriptor
1346 and value may be accessed by entering the described value.
1347
1348 >>> # read a symbolically described string
1349 >>> assert data.is_described() # will error if the current node is not described
1350 >>> data.enter()
1351 >>> print data.get_symbol()
1352 >>> print data.get_string()
1353 >>> data.exit()
1354 """
1355 return pn_data_is_described(self._data)
1356
1358 """
1359 Checks if the current node is a null.
1360 """
1361 self._check(pn_data_get_null(self._data))
1362
1364 """
1365 If the current node is a boolean, returns its value, returns False
1366 otherwise.
1367 """
1368 return pn_data_get_bool(self._data)
1369
1371 """
1372 If the current node is an unsigned byte, returns its value,
1373 returns 0 otherwise.
1374 """
1375 return pn_data_get_ubyte(self._data)
1376
1378 """
1379 If the current node is a signed byte, returns its value, returns 0
1380 otherwise.
1381 """
1382 return pn_data_get_byte(self._data)
1383
1385 """
1386 If the current node is an unsigned short, returns its value,
1387 returns 0 otherwise.
1388 """
1389 return pn_data_get_ushort(self._data)
1390
1392 """
1393 If the current node is a signed short, returns its value, returns
1394 0 otherwise.
1395 """
1396 return pn_data_get_short(self._data)
1397
1399 """
1400 If the current node is an unsigned int, returns its value, returns
1401 0 otherwise.
1402 """
1403 return pn_data_get_uint(self._data)
1404
1406 """
1407 If the current node is a signed int, returns its value, returns 0
1408 otherwise.
1409 """
1410 return pn_data_get_int(self._data)
1411
1413 """
1414 If the current node is a char, returns its value, returns 0
1415 otherwise.
1416 """
1417 return char(unichr(pn_data_get_char(self._data)))
1418
1420 """
1421 If the current node is an unsigned long, returns its value,
1422 returns 0 otherwise.
1423 """
1424 return ulong(pn_data_get_ulong(self._data))
1425
1427 """
1428 If the current node is an signed long, returns its value, returns
1429 0 otherwise.
1430 """
1431 return pn_data_get_long(self._data)
1432
1434 """
1435 If the current node is a timestamp, returns its value, returns 0
1436 otherwise.
1437 """
1438 return timestamp(pn_data_get_timestamp(self._data))
1439
1441 """
1442 If the current node is a float, returns its value, raises 0
1443 otherwise.
1444 """
1445 return pn_data_get_float(self._data)
1446
1448 """
1449 If the current node is a double, returns its value, returns 0
1450 otherwise.
1451 """
1452 return pn_data_get_double(self._data)
1453
1454
1456 """
1457 If the current node is a decimal32, returns its value, returns 0
1458 otherwise.
1459 """
1460 return pn_data_get_decimal32(self._data)
1461
1462
1464 """
1465 If the current node is a decimal64, returns its value, returns 0
1466 otherwise.
1467 """
1468 return pn_data_get_decimal64(self._data)
1469
1470
1472 """
1473 If the current node is a decimal128, returns its value, returns 0
1474 otherwise.
1475 """
1476 return pn_data_get_decimal128(self._data)
1477
1479 """
1480 If the current node is a UUID, returns its value, returns None
1481 otherwise.
1482 """
1483 if pn_data_type(self._data) == Data.UUID:
1484 return uuid.UUID(bytes=pn_data_get_uuid(self._data))
1485 else:
1486 return None
1487
1489 """
1490 If the current node is binary, returns its value, returns ""
1491 otherwise.
1492 """
1493 return pn_data_get_binary(self._data)
1494
1496 """
1497 If the current node is a string, returns its value, returns ""
1498 otherwise.
1499 """
1500 return pn_data_get_string(self._data).decode("utf8")
1501
1503 """
1504 If the current node is a symbol, returns its value, returns ""
1505 otherwise.
1506 """
1507 return symbol(pn_data_get_symbol(self._data))
1508
1509 - def copy(self, src):
1510 self._check(pn_data_copy(self._data, src._data))
1511
1522
1524 pn_data_dump(self._data)
1525
1535
1537 if self.enter():
1538 try:
1539 result = {}
1540 while self.next():
1541 k = self.get_object()
1542 if self.next():
1543 v = self.get_object()
1544 else:
1545 v = None
1546 result[k] = v
1547 finally:
1548 self.exit()
1549 return result
1550
1559
1561 if self.enter():
1562 try:
1563 result = []
1564 while self.next():
1565 result.append(self.get_object())
1566 finally:
1567 self.exit()
1568 return result
1569
1580
1589
1591 count, described, type = self.get_array()
1592 if self.enter():
1593 try:
1594 if described:
1595 self.next()
1596 descriptor = self.get_object()
1597 else:
1598 descriptor = UNDESCRIBED
1599 elements = []
1600 while self.next():
1601 elements.append(self.get_object())
1602 finally:
1603 self.exit()
1604 return Array(descriptor, type, *elements)
1605
1614
1615 put_mappings = {
1616 None.__class__: lambda s, _: s.put_null(),
1617 bool: put_bool,
1618 dict: put_dict,
1619 list: put_sequence,
1620 tuple: put_sequence,
1621 unicode: put_string,
1622 bytes: put_binary,
1623 symbol: put_symbol,
1624 int: put_long,
1625 char: put_char,
1626 long: put_long,
1627 ulong: put_ulong,
1628 timestamp: put_timestamp,
1629 float: put_double,
1630 uuid.UUID: put_uuid,
1631 Described: put_py_described,
1632 Array: put_py_array
1633 }
1634 get_mappings = {
1635 NULL: lambda s: None,
1636 BOOL: get_bool,
1637 BYTE: get_byte,
1638 UBYTE: get_ubyte,
1639 SHORT: get_short,
1640 USHORT: get_ushort,
1641 INT: get_int,
1642 UINT: get_uint,
1643 CHAR: get_char,
1644 LONG: get_long,
1645 ULONG: get_ulong,
1646 TIMESTAMP: get_timestamp,
1647 FLOAT: get_float,
1648 DOUBLE: get_double,
1649 DECIMAL32: get_decimal32,
1650 DECIMAL64: get_decimal64,
1651 DECIMAL128: get_decimal128,
1652 UUID: get_uuid,
1653 BINARY: get_binary,
1654 STRING: get_string,
1655 SYMBOL: get_symbol,
1656 DESCRIBED: get_py_described,
1657 ARRAY: get_py_array,
1658 LIST: get_sequence,
1659 MAP: get_dict
1660 }
1661
1663 putter = self.put_mappings[obj.__class__]
1664 putter(self, obj)
1665
1667 type = self.type()
1668 if type is None: return None
1669 getter = self.get_mappings.get(type)
1670 if getter:
1671 return getter(self)
1672 else:
1673 self.dump()
1674 return UnmappedType(str(type))
1675
1679
1681
1682 LOCAL_UNINIT = PN_LOCAL_UNINIT
1683 REMOTE_UNINIT = PN_REMOTE_UNINIT
1684 LOCAL_ACTIVE = PN_LOCAL_ACTIVE
1685 REMOTE_ACTIVE = PN_REMOTE_ACTIVE
1686 LOCAL_CLOSED = PN_LOCAL_CLOSED
1687 REMOTE_CLOSED = PN_REMOTE_CLOSED
1688
1690 self.condition = None
1691
1693 impl = self._get_cond_impl()
1694 pn_condition_clear(impl)
1695 if self.condition:
1696 pn_condition_set_name(impl, self.condition.name)
1697 pn_condition_set_description(impl, self.condition.description)
1698 info = Data(pn_condition_info(impl))
1699 if self.condition.info:
1700 info.put_object(self.condition.info)
1701
1702 @property
1704 impl = self._get_remote_cond_impl()
1705 if pn_condition_is_set(impl):
1706 info_impl = Data(pn_condition_info(impl))
1707 info_impl.rewind()
1708 info_impl.next()
1709 info = info_impl.get_object()
1710 info_impl.rewind()
1711 return Condition(pn_condition_get_name(impl),
1712 pn_condition_get_description(impl),
1713 info)
1714
1716
1717 - def __init__(self, name, description=None, info=None):
1718 self.name = name
1719 self.description = description
1720 self.info = info
1721
1723 return "Condition(%s)" % ", ".join([repr(x) for x in
1724 (self.name, self.description, self.info)
1725 if x])
1726
1728 if not isinstance(o, Condition): return False
1729 return self.name == o.name and \
1730 self.description == o.description and \
1731 self.info == o.info
1732
1734 if not conn: return None
1735 ctx = pn_connection_get_context(conn)
1736 if ctx: return ctx
1737 wrapper = Connection(_conn=conn)
1738 return wrapper
1739
1741
1743 Endpoint.__init__(self)
1744 if _conn:
1745 self._conn = _conn
1746 else:
1747 self._conn = pn_connection()
1748 pn_connection_set_context(self._conn, self)
1749
1751 if hasattr(self, "_conn"):
1752 pn_connection_free(self._conn)
1753 del self._conn
1754
1756 if err < 0:
1757 exc = EXCEPTIONS.get(err, ConnectionException)
1758 raise exc("[%s]: %s" % (err, pn_connection_error(self._conn)))
1759 else:
1760 return err
1761
1763 return pn_connection_condition(self._conn)
1764
1766 return pn_connection_remote_condition(self._conn)
1767
1769 return pn_connection_get_container(self._conn)
1771 return pn_connection_set_container(self._conn, name)
1772
1773 container = property(_get_container, _set_container)
1774
1776 return pn_connection_get_hostname(self._conn)
1778 return pn_connection_set_hostname(self._conn, name)
1779
1780 hostname = property(_get_hostname, _set_hostname)
1781
1782 @property
1784 return pn_connection_remote_container(self._conn)
1785
1786 @property
1788 return pn_connection_remote_hostname(self._conn)
1789
1790 @property
1792 return Data(pn_connection_offered_capabilities(self._conn))
1793
1794 @property
1796 return Data(pn_connection_desired_capabilities(self._conn))
1797
1798 @property
1800 return Data(pn_connection_remote_offered_capabilities(self._conn))
1801
1802 @property
1804 return Data(pn_connection_remote_desired_capabilities(self._conn))
1805
1807 pn_connection_open(self._conn)
1808
1810 self._update_cond()
1811 pn_connection_close(self._conn)
1812
1813 @property
1815 return pn_connection_state(self._conn)
1816
1817 @property
1819 return pn_connection_writable(self._conn)
1820
1822 return wrap_session(pn_session(self._conn))
1823
1825 return wrap_session(pn_session_head(self._conn, mask))
1826
1828 return wrap_link(pn_link_head(self._conn, mask))
1829
1830 @property
1832 return wrap_delivery(pn_work_head(self._conn))
1833
1836
1838 if ssn is None: return None
1839 ctx = pn_session_get_context(ssn)
1840 if ctx:
1841 return ctx
1842 else:
1843 wrapper = Session(ssn)
1844 pn_session_set_context(ssn, wrapper)
1845 return wrapper
1846
1848
1852
1854 if hasattr(self, "_ssn"):
1855 pn_session_free(self._ssn)
1856 del self._ssn
1857
1859 return pn_session_condition(self._ssn)
1860
1862 return pn_session_remote_condition(self._ssn)
1863
1865 pn_session_open(self._ssn)
1866
1868 self._update_cond()
1869 pn_session_close(self._ssn)
1870
1871 @property
1873 return pn_session_state(self._ssn)
1874
1875 @property
1877 return wrap_connection(pn_session_connection(self._ssn))
1878
1880 return wrap_link(pn_sender(self._ssn, name))
1881
1883 return wrap_link(pn_receiver(self._ssn, name))
1884
1887
1889 if link is None: return None
1890 ctx = pn_link_get_context(link)
1891 if ctx:
1892 return ctx
1893 else:
1894 if pn_link_is_sender(link):
1895 wrapper = Sender(link)
1896 else:
1897 wrapper = Receiver(link)
1898 pn_link_set_context(link, wrapper)
1899 return wrapper
1900
1901 -class Link(Endpoint):
1902
1906
1908 if hasattr(self, "_link"):
1909 pn_link_free(self._link)
1910 del self._link
1911
1913 if err < 0:
1914 exc = EXCEPTIONS.get(err, LinkException)
1915 raise exc("[%s]: %s" % (err, pn_link_error(self._link)))
1916 else:
1917 return err
1918
1920 return pn_link_condition(self._link)
1921
1923 return pn_link_remote_condition(self._link)
1924
1926 pn_link_open(self._link)
1927
1929 self._update_cond()
1930 pn_link_close(self._link)
1931
1932 @property
1934 return pn_link_state(self._link)
1935
1936 @property
1938 return Terminus(pn_link_source(self._link))
1939
1940 @property
1942 return Terminus(pn_link_target(self._link))
1943
1944 @property
1946 return Terminus(pn_link_remote_source(self._link))
1947 @property
1949 return Terminus(pn_link_remote_target(self._link))
1950
1951 @property
1953 return wrap_session(pn_link_session(self._link))
1954
1956 return wrap_delivery(pn_delivery(self._link, tag))
1957
1958 @property
1960 return wrap_delivery(pn_link_current(self._link))
1961
1963 return pn_link_advance(self._link)
1964
1965 @property
1967 return pn_link_unsettled(self._link)
1968
1969 @property
1971 return pn_link_credit(self._link)
1972
1973 @property
1975 return pn_link_available(self._link)
1976
1977 @property
1979 return pn_link_queued(self._link)
1980
1981 - def next(self, mask):
1982 return wrap_link(pn_link_next(self._link, mask))
1983
1985
1986 UNSPECIFIED = PN_UNSPECIFIED
1987 SOURCE = PN_SOURCE
1988 TARGET = PN_TARGET
1989 COORDINATOR = PN_COORDINATOR
1990
1991 NONDURABLE = PN_NONDURABLE
1992 CONFIGURATION = PN_CONFIGURATION
1993 DELIVERIES = PN_DELIVERIES
1994
1997
1999 if err < 0:
2000 exc = EXCEPTIONS.get(err, LinkException)
2001 raise exc("[%s]" % err)
2002 else:
2003 return err
2004
2006 return pn_terminus_get_type(self._impl)
2008 self._check(pn_terminus_set_type(self._impl, type))
2009 type = property(_get_type, _set_type)
2010
2012 return pn_terminus_get_address(self._impl)
2014 self._check(pn_terminus_set_address(self._impl, address))
2015 address = property(_get_address, _set_address)
2016
2018 return pn_terminus_get_durability(self._impl)
2020 self._check(pn_terminus_set_durability(self._impl, seconds))
2021 durability = property(_get_durability, _set_durability)
2022
2024 return pn_terminus_get_expiry_policy(self._impl)
2026 self._check(pn_terminus_set_expiry_policy(self._impl, seconds))
2027 expiry_policy = property(_get_expiry_policy, _set_expiry_policy)
2028
2030 return pn_terminus_get_timeout(self._impl)
2032 self._check(pn_terminus_set_timeout(self._impl, seconds))
2033 timeout = property(_get_timeout, _set_timeout)
2034
2036 return pn_terminus_is_dynamic(self._impl)
2038 self._check(pn_terminus_set_dynamic(self._impl, dynamic))
2039 dynamic = property(_is_dynamic, _set_dynamic)
2040
2041 @property
2043 return Data(pn_terminus_properties(self._impl))
2044
2045 @property
2047 return Data(pn_terminus_capabilities(self._impl))
2048
2049 @property
2051 return Data(pn_terminus_outcomes(self._impl))
2052
2053 @property
2055 return Data(pn_terminus_filter(self._impl))
2056
2057 - def copy(self, src):
2058 self._check(pn_terminus_copy(self._impl, src._impl))
2059
2062
2064 pn_link_offered(self._link, n)
2065
2066 - def send(self, bytes):
2067 return self._check(pn_link_send(self._link, bytes))
2068
2070 pn_link_drained(self._link)
2071
2073
2074 - def flow(self, n):
2075 pn_link_flow(self._link, n)
2076
2077 - def recv(self, limit):
2078 n, bytes = pn_link_recv(self._link, limit)
2079 if n == PN_EOS:
2080 return None
2081 else:
2082 self._check(n)
2083 return bytes
2084
2086 pn_link_drain(self._link, n)
2087
2089 if not dlv: return None
2090 ctx = pn_delivery_get_context(dlv)
2091 if ctx: return ctx
2092 wrapper = Delivery(dlv)
2093 pn_delivery_set_context(dlv, wrapper)
2094 return wrapper
2095
2097
2098 ACCEPTED = PN_ACCEPTED
2099
2102
2103 @property
2105 return pn_delivery_tag(self._dlv)
2106
2107 @property
2109 return pn_delivery_writable(self._dlv)
2110
2111 @property
2113 return pn_delivery_readable(self._dlv)
2114
2115 @property
2117 return pn_delivery_updated(self._dlv)
2118
2120 pn_delivery_update(self._dlv, state)
2121
2122 @property
2124 return pn_delivery_local_state(self._dlv)
2125
2126 @property
2128 return pn_delivery_remote_state(self._dlv)
2129
2130 @property
2132 return pn_delivery_settled(self._dlv)
2133
2135 pn_delivery_settle(self._dlv)
2136
2137 @property
2139 return wrap_delivery(pn_work_next(self._dlv))
2140
2143
2145
2146 TRACE_DRV = PN_TRACE_DRV
2147 TRACE_FRM = PN_TRACE_FRM
2148 TRACE_RAW = PN_TRACE_RAW
2149
2151 self._trans = pn_transport()
2152
2154 if hasattr(self, "_trans"):
2155 pn_transport_free(self._trans)
2156 del self._trans
2157
2159 if err < 0:
2160 exc = EXCEPTIONS.get(err, TransportException)
2161 raise exc("[%s]: %s" % (err, pn_error_text(pn_transport_error(self._trans))))
2162 else:
2163 return err
2164
2165 - def bind(self, connection):
2166 self._check(pn_transport_bind(self._trans, connection._conn))
2167
2169 pn_transport_trace(self._trans, n)
2170
2171 - def tick(self, now):
2172 return pn_transport_tick(self._trans, now)
2173
2175 cd, out = pn_transport_output(self._trans, n)
2176 if cd == PN_EOS:
2177 return None
2178 else:
2179 self._check(cd)
2180 return out
2181
2188
2189
2191 return pn_transport_get_max_frame(self._trans)
2192
2194 pn_transport_set_max_frame(self._trans, value)
2195
2196 max_frame_size = property(_get_max_frame_size, _set_max_frame_size,
2197 doc="""
2198 Sets the maximum size for received frames (in bytes).
2199 """)
2200
2201 @property
2203 return pn_transport_get_remote_max_frame(self._trans)
2204
2205
2207 return pn_transport_get_idle_timeout(self._trans)
2208
2210 pn_transport_set_idle_timeout(self._trans, value)
2211
2212 idle_timeout = property(_get_idle_timeout, _set_idle_timeout,
2213 doc="""
2214 The idle timeout of the connection (in milliseconds).
2215 """)
2216
2217 @property
2219 return pn_transport_get_remote_idle_timeout(self._trans)
2220
2221 @property
2223 return pn_transport_get_frames_output(self._trans)
2224
2225 @property
2228
2231
2232 -class SASL(object):
2233
2234 OK = PN_SASL_OK
2235 AUTH = PN_SASL_AUTH
2236
2238 self._sasl = pn_sasl(transport._trans)
2239
2241 if err < 0:
2242 exc = EXCEPTIONS.get(err, SASLException)
2243 raise exc("[%s]" % (err))
2244 else:
2245 return err
2246
2248 pn_sasl_mechanisms(self._sasl, mechs)
2249
2251 pn_sasl_client(self._sasl)
2252
2254 pn_sasl_server(self._sasl)
2255
2256 - def plain(self, user, password):
2257 pn_sasl_plain(self._sasl, user, password)
2258
2259 - def send(self, data):
2260 self._check(pn_sasl_send(self._sasl, data, len(data)))
2261
2263 sz = 16
2264 while True:
2265 n, data = pn_sasl_recv(self._sasl, sz)
2266 if n == PN_OVERFLOW:
2267 sz *= 2
2268 continue
2269 elif n == PN_EOS:
2270 return None
2271 else:
2272 self._check(n)
2273 return data
2274
2275 @property
2277 outcome = pn_sasl_outcome(self._sasl)
2278 if outcome == PN_SASL_NONE:
2279 return None
2280 else:
2281 return outcome
2282
2283 - def done(self, outcome):
2284 pn_sasl_done(self._sasl, outcome)
2285
2288
2291
2292 -class SSLDomain(object):
2293
2294 MODE_CLIENT = PN_SSL_MODE_CLIENT
2295 MODE_SERVER = PN_SSL_MODE_SERVER
2296 VERIFY_PEER = PN_SSL_VERIFY_PEER
2297 VERIFY_PEER_NAME = PN_SSL_VERIFY_PEER_NAME
2298 ANONYMOUS_PEER = PN_SSL_ANONYMOUS_PEER
2299
2300 - def __init__(self, mode):
2301 self._domain = pn_ssl_domain(mode)
2302 if self._domain is None:
2303 raise SSLUnavailable()
2304
2305 - def _check(self, err):
2306 if err < 0:
2307 exc = EXCEPTIONS.get(err, SSLException)
2308 raise exc("SSL failure.")
2309 else:
2310 return err
2311
2312 - def set_credentials(self, cert_file, key_file, password):
2313 return self._check( pn_ssl_domain_set_credentials(self._domain,
2314 cert_file, key_file,
2315 password) )
2316 - def set_trusted_ca_db(self, certificate_db):
2317 return self._check( pn_ssl_domain_set_trusted_ca_db(self._domain,
2318 certificate_db) )
2319 - def set_peer_authentication(self, verify_mode, trusted_CAs=None):
2320 return self._check( pn_ssl_domain_set_peer_authentication(self._domain,
2321 verify_mode,
2322 trusted_CAs) )
2323
2325 return self._check( pn_ssl_domain_allow_unsecured_client(self._domain) )
2326
2328
2330 if err < 0:
2331 exc = EXCEPTIONS.get(err, SSLException)
2332 raise exc("SSL failure.")
2333 else:
2334 return err
2335
2336 - def __init__(self, transport, domain, session_details=None):
2337 session_id = None
2338 if session_details:
2339 session_id = session_details.get_session_id()
2340 self._ssl = pn_ssl( transport._trans )
2341 if self._ssl is None:
2342 raise SSLUnavailable()
2343 pn_ssl_init( self._ssl, domain._domain, session_id )
2344
2346 rc, name = pn_ssl_get_cipher_name( self._ssl, 128 )
2347 if rc:
2348 return name
2349 return None
2350
2352 rc, name = pn_ssl_get_protocol_name( self._ssl, 128 )
2353 if rc:
2354 return name
2355 return None
2356
2357 RESUME_UNKNOWN = PN_SSL_RESUME_UNKNOWN
2358 RESUME_NEW = PN_SSL_RESUME_NEW
2359 RESUME_REUSED = PN_SSL_RESUME_REUSED
2360
2362 return pn_ssl_resume_status( self._ssl )
2363
2365 self._check(pn_ssl_set_peer_hostname( self._ssl, hostname ))
2367 err, name = pn_ssl_get_peer_hostname( self._ssl, 1024 )
2368 self._check(err)
2369 return name
2370 peer_hostname = property(_get_peer_hostname, _set_peer_hostname,
2371 doc="""
2372 Manage the expected name of the remote peer. Used to authenticate the remote.
2373 """)
2374
2377 """ Unique identifier for the SSL session. Used to resume previous session on a new
2378 SSL connection.
2379 """
2380
2382 self._session_id = session_id
2383
2385 return self._session_id
2386
2387 __all__ = [
2388 "LANGUAGE",
2389 "PN_SESSION_WINDOW",
2390 "ACCEPTED",
2391 "AUTOMATIC",
2392 "PENDING",
2393 "MANUAL",
2394 "REJECTED",
2395 "UNDESCRIBED",
2396 "Array",
2397 "Condition",
2398 "Connection",
2399 "Data",
2400 "Delivery",
2401 "Described",
2402 "Endpoint",
2403 "Link",
2404 "Message",
2405 "MessageException",
2406 "Messenger",
2407 "MessengerException",
2408 "ProtonException",
2409 "Receiver",
2410 "SASL",
2411 "Sender",
2412 "Session",
2413 "SSL",
2414 "SSLDomain",
2415 "SSLSessionDetails",
2416 "SSLUnavailable",
2417 "Terminus",
2418 "Timeout",
2419 "Transport",
2420 "TransportException",
2421 "char",
2422 "symbol",
2423 "timestamp",
2424 "ulong"
2425 ]
2426