1# 2# Licensed to the Apache Software Foundation (ASF) under one 3# or more contributor license agreements. See the NOTICE file 4# distributed with this work for additional information 5# regarding copyright ownership. The ASF licenses this file 6# to you under the Apache License, Version 2.0 (the 7# "License"); you may not use this file except in compliance 8# with the License. You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, 13# software distributed under the License is distributed on an 14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15# KIND, either express or implied. See the License for the 16# specific language governing permissions and limitations 17# under the License. 18# 19 20""" 21The proton module defines a suite of APIs that implement the AMQP 1.0 22protocol. 23 24The 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""" 32from__future__importabsolute_import 33 34fromcprotonimport* 35from.wrapperimportWrapper 36fromprotonimport_compat 37 38importlogging,weakref,socket,sys,threading 39 40try: 41handler=logging.NullHandler() 42exceptAttributeError:

100data=[rand.randint(0,255)foriinxrange(16)] 101 102# From RFC4122, the version bits are set to 0100 103data[6]&=0x0F 104data[6]|=0x40 105 106# From RFC4122, the top two bits of byte 8 get set to 01 107data[8]&=0x3F 108data[8]|=0x80 109return"".join(map(chr,data))

212""" 213 The L{Messenger} class defines a high level interface for sending 214 and receiving L{Messages<Message>}. Every L{Messenger} contains a 215 single logical queue of incoming messages and a single logical queue 216 of outgoing messages. These messages in these queues may be destined 217 for, or originate from, a variety of addresses. 218 219 The messenger interface is single-threaded. All methods 220 except one (L{interrupt}) are intended to be used from within 221 the messenger thread. 222 223 224 Address Syntax 225 ============== 226 227 An address has the following form:: 228 229 [ amqp[s]:// ] [user[:password]@] domain [/[name]] 230 231 Where domain can be one of:: 232 233 host | host:port | ip | ip:port | name 234 235 The following are valid examples of addresses: 236 237 - example.org 238 - example.org:1234 239 - amqp://example.org 240 - amqps://example.org 241 - example.org/incoming 242 - amqps://example.org/outgoing 243 - amqps://fred:trustno1@example.org 244 - 127.0.0.1:1234 245 - amqps://127.0.0.1:1234 246 247 Sending & Receiving Messages 248 ============================ 249 250 The L{Messenger} class works in conjunction with the L{Message} class. The 251 L{Message} class is a mutable holder of message content. 252 253 The L{put} method copies its L{Message} to the outgoing queue, and may 254 send queued messages if it can do so without blocking. The L{send} 255 method blocks until it has sent the requested number of messages, 256 or until a timeout interrupts the attempt. 257 258 259 >>> message = Message() 260 >>> for i in range(3): 261 ... message.address = "amqp://host/queue" 262 ... message.subject = "Hello World %i" % i 263 ... messenger.put(message) 264 >>> messenger.send() 265 266 Similarly, the L{recv} method receives messages into the incoming 267 queue, and may block as it attempts to receive the requested number 268 of messages, or until timeout is reached. It may receive fewer 269 than the requested number. The L{get} method pops the 270 eldest L{Message} off the incoming queue and copies it into the L{Message} 271 object that you supply. It will not block. 272 273 274 >>> message = Message() 275 >>> messenger.recv(10): 276 >>> while messenger.incoming > 0: 277 ... messenger.get(message) 278 ... print message.subject 279 Hello World 0 280 Hello World 1 281 Hello World 2 282 283 The blocking flag allows you to turn off blocking behavior entirely, 284 in which case L{send} and L{recv} will do whatever they can without 285 blocking, and then return. You can then look at the number 286 of incoming and outgoing messages to see how much outstanding work 287 still remains. 288 """ 289

291""" 292 Construct a new L{Messenger} with the given name. The name has 293 global scope. If a NULL name is supplied, a UUID based name will 294 be chosen. 295 296 @type name: string 297 @param name: the name of the messenger or None 298 299 """ 300self._mng=pn_messenger(name) 301self._selectables={}

304""" 305 Destroy the L{Messenger}. This will close all connections that 306 are managed by the L{Messenger}. Call the L{stop} method before 307 destroying the L{Messenger}. 308 """ 309ifhasattr(self,"_mng"): 310pn_messenger_free(self._mng) 311delself._mng

334 335certificate=property(_get_certificate,_set_certificate, 336doc=""" 337Path to a certificate file for the L{Messenger}. This certificate is 338used when the L{Messenger} accepts or establishes SSL/TLS connections. 339This property must be specified for the L{Messenger} to accept 340incoming SSL/TLS connections and to establish client authenticated 341outgoing SSL/TLS connection. Non client authenticated outgoing SSL/TLS 342connections do not require this property. 343""") 344

350 351private_key=property(_get_private_key,_set_private_key, 352doc=""" 353Path to a private key file for the L{Messenger's<Messenger>} 354certificate. This property must be specified for the L{Messenger} to 355accept incoming SSL/TLS connections and to establish client 356authenticated outgoing SSL/TLS connection. Non client authenticated 357SSL/TLS connections do not require this property. 358""") 359

377 378trusted_certificates=property(_get_trusted_certificates, 379_set_trusted_certificates, 380doc=""" 381A path to a database of trusted certificates for use in verifying the 382peer on an SSL/TLS connection. If this property is None, then the peer 383will not be verified. 384""") 385

425 426passive=property(_is_passive,_set_passive, 427doc=""" 428When passive is set to true, Messenger will not attempt to perform I/O 429internally. In this mode it is necessary to use the selectables API to 430drive any I/O needed to perform requested actions. In this mode 431Messenger will never block. 432""") 433

439 440incoming_window=property(_get_incoming_window,_set_incoming_window, 441doc=""" 442The incoming tracking window for the messenger. The messenger will 443track the remote status of this many incoming deliveries after they 444have been accepted or rejected. Defaults to zero. 445 446L{Messages<Message>} enter this window only when you take them into your application 447using L{get}. If your incoming window size is I{n}, and you get I{n}+1 L{messages<Message>} 448without explicitly accepting or rejecting the oldest message, then the 449message that passes beyond the edge of the incoming window will be assigned 450the default disposition of its link. 451""") 452

458 459outgoing_window=property(_get_outgoing_window,_set_outgoing_window, 460doc=""" 461The outgoing tracking window for the messenger. The messenger will 462track the remote status of this many outgoing deliveries after calling 463send. Defaults to zero. 464 465A L{Message} enters this window when you call the put() method with the 466message. If your outgoing window size is I{n}, and you call L{put} I{n}+1 467times, status information will no longer be available for the 468first message. 469""") 470

480""" 481 Transitions the L{Messenger} to an inactive state. An inactive 482 L{Messenger} will not send or receive messages from its internal 483 queues. A L{Messenger} should be stopped before being discarded to 484 ensure a clean shutdown handshake occurs on any internally managed 485 connections. 486 """ 487self._check(pn_messenger_stop(self._mng))

498""" 499 Subscribes the L{Messenger} to messages originating from the 500 specified source. The source is an address as specified in the 501 L{Messenger} introduction with the following addition. If the 502 domain portion of the address begins with the '~' character, the 503 L{Messenger} will interpret the domain as host/port, bind to it, 504 and listen for incoming messages. For example "~0.0.0.0", 505 "amqp://~0.0.0.0", and "amqps://~0.0.0.0" will all bind to any 506 local interface and listen for incoming messages with the last 507 variant only permitting incoming SSL connections. 508 509 @type source: string 510 @param source: the source of messages to subscribe to 511 """ 512sub_impl=pn_messenger_subscribe(self._mng,source) 513ifnotsub_impl: 514self._check(pn_error_code(pn_messenger_error(self._mng))) 515raiseMessengerException("Cannot subscribe to %s"%source) 516returnSubscription(sub_impl)

519""" 520 Places the content contained in the message onto the outgoing 521 queue of the L{Messenger}. This method will never block, however 522 it will send any unblocked L{Messages<Message>} in the outgoing 523 queue immediately and leave any blocked L{Messages<Message>} 524 remaining in the outgoing queue. The L{send} call may be used to 525 block until the outgoing queue is empty. The L{outgoing} property 526 may be used to check the depth of the outgoing queue. 527 528 When the content in a given L{Message} object is copied to the outgoing 529 message queue, you may then modify or discard the L{Message} object 530 without having any impact on the content in the outgoing queue. 531 532 This method returns an outgoing tracker for the L{Message}. The tracker 533 can be used to determine the delivery status of the L{Message}. 534 535 @type message: Message 536 @param message: the message to place in the outgoing queue 537 @return: a tracker 538 """ 539message._pre_encode() 540self._check(pn_messenger_put(self._mng,message._msg)) 541returnpn_messenger_outgoing_tracker(self._mng)

544""" 545 Gets the last known remote state of the delivery associated with 546 the given tracker. 547 548 @type tracker: tracker 549 @param tracker: the tracker whose status is to be retrieved 550 551 @return: one of None, PENDING, REJECTED, MODIFIED, or ACCEPTED 552 """ 553disp=pn_messenger_status(self._mng,tracker); 554returnSTATUSES.get(disp,disp)

557""" 558 Checks if the delivery associated with the given tracker is still 559 waiting to be sent. 560 561 @type tracker: tracker 562 @param tracker: the tracker whose status is to be retrieved 563 564 @return: true if delivery is still buffered 565 """ 566returnpn_messenger_buffered(self._mng,tracker);

569""" 570 Frees a L{Messenger} from tracking the status associated with a given 571 tracker. If you don't supply a tracker, all outgoing L{messages<Message>} up 572 to the most recent will be settled. 573 """ 574iftrackerisNone: 575tracker=pn_messenger_outgoing_tracker(self._mng) 576flags=PN_CUMULATIVE 577else: 578flags=0 579self._check(pn_messenger_settle(self._mng,tracker,flags))

582""" 583 This call will block until the indicated number of L{messages<Message>} 584 have been sent, or until the operation times out. If n is -1 this call will 585 block until all outgoing L{messages<Message>} have been sent. If n is 0 then 586 this call will send whatever it can without blocking. 587 """ 588self._check(pn_messenger_send(self._mng,n))

591""" 592 Receives up to I{n} L{messages<Message>} into the incoming queue. If no value 593 for I{n} is supplied, this call will receive as many L{messages<Message>} as it 594 can buffer internally. If the L{Messenger} is in blocking mode, this 595 call will block until at least one L{Message} is available in the 596 incoming queue. 597 """ 598ifnisNone: 599n=-1 600self._check(pn_messenger_recv(self._mng,n))

603""" 604 Sends or receives any outstanding L{messages<Message>} queued for a L{Messenger}. 605 This will block for the indicated timeout. 606 This method may also do I/O work other than sending and receiving 607 L{messages<Message>}. For example, closing connections after messenger.L{stop}() 608 has been called. 609 """ 610iftimeoutisNone: 611t=-1 612else: 613t=secs2millis(timeout) 614err=pn_messenger_work(self._mng,t) 615if(err==PN_TIMEOUT): 616returnFalse 617else: 618self._check(err) 619returnTrue

626""" 627 The L{Messenger} interface is single-threaded. 628 This is the only L{Messenger} function intended to be called 629 from outside of the L{Messenger} thread. 630 Call this from a non-messenger thread to interrupt 631 a L{Messenger} that is blocking. 632 This will cause any in-progress blocking call to throw 633 the L{Interrupt} exception. If there is no currently blocking 634 call, then the next blocking call will be affected, even if it 635 is within the same thread that interrupt was called from. 636 """ 637self._check(pn_messenger_interrupt(self._mng))

640""" 641 Moves the message from the head of the incoming message queue into 642 the supplied message object. Any content in the message will be 643 overwritten. 644 645 A tracker for the incoming L{Message} is returned. The tracker can 646 later be used to communicate your acceptance or rejection of the 647 L{Message}. 648 649 If None is passed in for the L{Message} object, the L{Message} 650 popped from the head of the queue is discarded. 651 652 @type message: Message 653 @param message: the destination message object 654 @return: a tracker 655 """ 656ifmessageisNone: 657impl=None 658else: 659impl=message._msg 660self._check(pn_messenger_get(self._mng,impl)) 661ifmessageisnotNone: 662message._post_decode() 663returnpn_messenger_incoming_tracker(self._mng)

666""" 667 Signal the sender that you have acted on the L{Message} 668 pointed to by the tracker. If no tracker is supplied, 669 then all messages that have been returned by the L{get} 670 method are accepted, except those that have already been 671 auto-settled by passing beyond your incoming window size. 672 673 @type tracker: tracker 674 @param tracker: a tracker as returned by get 675 """ 676iftrackerisNone: 677tracker=pn_messenger_incoming_tracker(self._mng) 678flags=PN_CUMULATIVE 679else: 680flags=0 681self._check(pn_messenger_accept(self._mng,tracker,flags))

684""" 685 Rejects the L{Message} indicated by the tracker. If no tracker 686 is supplied, all messages that have been returned by the L{get} 687 method are rejected, except those that have already been auto-settled 688 by passing beyond your outgoing window size. 689 690 @type tracker: tracker 691 @param tracker: a tracker as returned by get 692 """ 693iftrackerisNone: 694tracker=pn_messenger_incoming_tracker(self._mng) 695flags=PN_CUMULATIVE 696else: 697flags=0 698self._check(pn_messenger_reject(self._mng,tracker,flags))

715""" 716 Adds a routing rule to a L{Messenger's<Messenger>} internal routing table. 717 718 The route procedure may be used to influence how a L{Messenger} will 719 internally treat a given address or class of addresses. Every call 720 to the route procedure will result in L{Messenger} appending a routing 721 rule to its internal routing table. 722 723 Whenever a L{Message} is presented to a L{Messenger} for delivery, it 724 will match the address of this message against the set of routing 725 rules in order. The first rule to match will be triggered, and 726 instead of routing based on the address presented in the message, 727 the L{Messenger} will route based on the address supplied in the rule. 728 729 The pattern matching syntax supports two types of matches, a '%' 730 will match any character except a '/', and a '*' will match any 731 character including a '/'. 732 733 A routing address is specified as a normal AMQP address, however it 734 may additionally use substitution variables from the pattern match 735 that triggered the rule. 736 737 Any message sent to "foo" will be routed to "amqp://foo.com": 738 739 >>> messenger.route("foo", "amqp://foo.com"); 740 741 Any message sent to "foobar" will be routed to 742 "amqp://foo.com/bar": 743 744 >>> messenger.route("foobar", "amqp://foo.com/bar"); 745 746 Any message sent to bar/<path> will be routed to the corresponding 747 path within the amqp://bar.com domain: 748 749 >>> messenger.route("bar/*", "amqp://bar.com/$1"); 750 751 Route all L{messages<Message>} over TLS: 752 753 >>> messenger.route("amqp:*", "amqps:$1") 754 755 Supply credentials for foo.com: 756 757 >>> messenger.route("amqp://foo.com/*", "amqp://user:password@foo.com/$1"); 758 759 Supply credentials for all domains: 760 761 >>> messenger.route("amqp://*", "amqp://user:password@$1"); 762 763 Route all addresses through a single proxy while preserving the 764 original destination: 765 766 >>> messenger.route("amqp://%/*", "amqp://user:password@proxy/$1/$2"); 767 768 Route any address through a single broker: 769 770 >>> messenger.route("*", "amqp://user:password@broker/$1"); 771 """ 772self._check(pn_messenger_route(self._mng,unicode2utf8(pattern),unicode2utf8(address)))

775""" 776 Similar to route(), except that the destination of 777 the L{Message} is determined before the message address is rewritten. 778 779 The outgoing address is only rewritten after routing has been 780 finalized. If a message has an outgoing address of 781 "amqp://0.0.0.0:5678", and a rewriting rule that changes its 782 outgoing address to "foo", it will still arrive at the peer that 783 is listening on "amqp://0.0.0.0:5678", but when it arrives there, 784 the receiver will see its outgoing address as "foo". 785 786 The default rewrite rule removes username and password from addresses 787 before they are transmitted. 788 """ 789self._check(pn_messenger_rewrite(self._mng,unicode2utf8(pattern),unicode2utf8(address)))

895""" 896 Clears the contents of the L{Message}. All fields will be reset to 897 their default values. 898 """ 899pn_message_clear(self._msg) 900self.instructions=None 901self.annotations=None 902self.properties=None 903self.body=None

910 911inferred=property(_is_inferred,_set_inferred,doc=""" 912The inferred flag for a message indicates how the message content 913is encoded into AMQP sections. If inferred is true then binary and 914list values in the body of the message will be encoded as AMQP DATA 915and AMQP SEQUENCE sections, respectively. If inferred is false, 916then all values in the body of the message will be encoded as AMQP 917VALUE sections regardless of their type. 918""") 919

925 926durable=property(_is_durable,_set_durable, 927doc=""" 928The durable property indicates that the message should be held durably 929by any intermediaries taking responsibility for the message. 930""") 931

1150"""1151 Receives and decodes the message content for the current delivery1152 from the link. Upon success it will return the current delivery1153 for the link. If there is no current delivery, or if the current1154 delivery is incomplete, or if the link is not a receiver, it will1155 return None.11561157 @type link: Link1158 @param link: the link to receive a message from1159 @return the delivery associated with the decoded message (or None)11601161 """1162iflink.is_sender:returnNone1163dlv=link.current1164ifnotdlvordlv.partial:returnNone1165dlv.encoded=link.recv(dlv.pending)1166link.advance()1167# the sender has already forgotten about the delivery, so we might1168# as well too1169iflink.remote_snd_settle_mode==Link.SND_SETTLED:1170dlv.settle()1171self.decode(dlv.encoded)1172returndlv

12691270registered=property(_is_registered,_set_registered,1271doc="""1272The registered property may be get/set by an I/O polling system to1273indicate whether the fd has been registered or not.1274""")12751276@property

1413"""1414 The L{Data} class provides an interface for decoding, extracting,1415 creating, and encoding arbitrary AMQP data. A L{Data} object1416 contains a tree of AMQP values. Leaf nodes in this tree correspond1417 to scalars in the AMQP type system such as L{ints<INT>} or1418 L{strings<STRING>}. Non-leaf nodes in this tree correspond to1419 compound values in the AMQP type system such as L{lists<LIST>},1420 L{maps<MAP>}, L{arrays<ARRAY>}, or L{described values<DESCRIBED>}.1421 The root node of the tree is the L{Data} object itself and can have1422 an arbitrary number of children.14231424 A L{Data} object maintains the notion of the current sibling node1425 and a current parent node. Siblings are ordered within their parent.1426 Values are accessed and/or added by using the L{next}, L{prev},1427 L{enter}, and L{exit} methods to navigate to the desired location in1428 the tree and using the supplied variety of put_*/get_* methods to1429 access or add a value of the desired type.14301431 The put_* methods will always add a value I{after} the current node1432 in the tree. If the current node has a next sibling the put_* method1433 will overwrite the value on this node. If there is no current node1434 or the current node has no next sibling then one will be added. The1435 put_* methods always set the added/modified node to the current1436 node. The get_* methods read the value of the current node and do1437 not change which node is current.14381439 The following types of scalar values are supported:14401441 - L{NULL}1442 - L{BOOL}1443 - L{UBYTE}1444 - L{USHORT}1445 - L{SHORT}1446 - L{UINT}1447 - L{INT}1448 - L{ULONG}1449 - L{LONG}1450 - L{FLOAT}1451 - L{DOUBLE}1452 - L{BINARY}1453 - L{STRING}1454 - L{SYMBOL}14551456 The following types of compound values are supported:14571458 - L{DESCRIBED}1459 - L{ARRAY}1460 - L{LIST}1461 - L{MAP}1462 """14631464NULL=PN_NULL;"A null value."1465BOOL=PN_BOOL;"A boolean value."1466UBYTE=PN_UBYTE;"An unsigned byte value."1467BYTE=PN_BYTE;"A signed byte value."1468USHORT=PN_USHORT;"An unsigned short value."1469SHORT=PN_SHORT;"A short value."1470UINT=PN_UINT;"An unsigned int value."1471INT=PN_INT;"A signed int value."1472CHAR=PN_CHAR;"A character value."1473ULONG=PN_ULONG;"An unsigned long value."1474LONG=PN_LONG;"A signed long value."1475TIMESTAMP=PN_TIMESTAMP;"A timestamp value."1476FLOAT=PN_FLOAT;"A float value."1477DOUBLE=PN_DOUBLE;"A double value."1478DECIMAL32=PN_DECIMAL32;"A DECIMAL32 value."1479DECIMAL64=PN_DECIMAL64;"A DECIMAL64 value."1480DECIMAL128=PN_DECIMAL128;"A DECIMAL128 value."1481UUID=PN_UUID;"A UUID value."1482BINARY=PN_BINARY;"A binary string."1483STRING=PN_STRING;"A unicode string."1484SYMBOL=PN_SYMBOL;"A symbolic string."1485DESCRIBED=PN_DESCRIBED;"A described value."1486ARRAY=PN_ARRAY;"An array value."1487LIST=PN_LIST;"A list value."1488MAP=PN_MAP;"A map value."14891490type_names={1491NULL:"null",1492BOOL:"bool",1493BYTE:"byte",1494UBYTE:"ubyte",1495SHORT:"short",1496USHORT:"ushort",1497INT:"int",1498UINT:"uint",1499CHAR:"char",1500LONG:"long",1501ULONG:"ulong",1502TIMESTAMP:"timestamp",1503FLOAT:"float",1504DOUBLE:"double",1505DECIMAL32:"decimal32",1506DECIMAL64:"decimal64",1507DECIMAL128:"decimal128",1508UUID:"uuid",1509BINARY:"binary",1510STRING:"string",1511SYMBOL:"symbol",1512DESCRIBED:"described",1513ARRAY:"array",1514LIST:"list",1515MAP:"map"1516}15171518@classmethod

1548"""1549 Clears current node and sets the parent to the root node. Clearing the1550 current node sets it _before_ the first node, calling next() will advance to1551 the first node.1552 """1553assertself._dataisnotNone1554pn_data_rewind(self._data)

1557"""1558 Advances the current node to its next sibling and returns its1559 type. If there is no next sibling the current node remains1560 unchanged and None is returned.1561 """1562found=pn_data_next(self._data)1563iffound:1564returnself.type()1565else:1566returnNone

1569"""1570 Advances the current node to its previous sibling and returns its1571 type. If there is no previous sibling the current node remains1572 unchanged and None is returned.1573 """1574found=pn_data_prev(self._data)1575iffound:1576returnself.type()1577else:1578returnNone

1581"""1582 Sets the parent node to the current node and clears the current node.1583 Clearing the current node sets it _before_ the first child,1584 call next() advances to the first child.1585 """1586returnpn_data_enter(self._data)

1621"""1622 Returns a representation of the data encoded in AMQP format.1623 """1624size=10241625whileTrue:1626cd,enc=pn_data_encode(self._data,size)1627ifcd==PN_OVERFLOW:1628size*=21629elifcd>=0:1630returnenc1631else:1632self._check(cd)

1958"""1959 Checks if the current node is a described value. The descriptor1960 and value may be accessed by entering the described value.19611962 >>> # read a symbolically described string1963 >>> assert data.is_described() # will error if the current node is not described1964 >>> data.enter()1965 >>> data.next()1966 >>> print data.get_symbol()1967 >>> data.next()1968 >>> print data.get_string()1969 >>> data.exit()1970 """1971returnpn_data_is_described(self._data)

2095"""2096 If the current node is a UUID, returns its value, returns None2097 otherwise.2098 """2099ifpn_data_type(self._data)==Data.UUID:2100returnuuid.UUID(bytes=pn_data_get_uuid(self._data))2101else:2102returnNone

2207"""2208 If the current node is an array, return an Array object2209 representing the array and its contents. Otherwise return None.2210 This is a convenience wrapper around get_array, enter, etc.2211 """22122213count,described,type=self.get_array()2214iftypeisNone:returnNone2215ifself.enter():2216try:2217ifdescribed:2218self.next()2219descriptor=self.get_object()2220else:2221descriptor=UNDESCRIBED2222elements=[]2223whileself.next():2224elements.append(self.get_object())2225finally:2226self.exit()2227returnArray(descriptor,type,*elements)

25362537hostname=property(_get_hostname,_set_hostname,2538doc="""2539Set the name of the host (either fully qualified or relative) to which this2540connection is connecting to. This information may be used by the remote2541peer to determine the correct back-end service to connect the client to.2542This value will be sent in the Open performative, and will be used by SSL2543and SASL layers to identify the peer.2544""")2545

2586"""2587 Opens the connection.25882589 In more detail, this moves the local state of the connection to2590 the ACTIVE state and triggers an open frame to be sent to the2591 peer. A connection is fully active once both peers have opened it.2592 """2593obj2dat(self.offered_capabilities,2594pn_connection_offered_capabilities(self._impl))2595obj2dat(self.desired_capabilities,2596pn_connection_desired_capabilities(self._impl))2597obj2dat(self.properties,pn_connection_properties(self._impl))2598pn_connection_open(self._impl)

2601"""2602 Closes the connection.26032604 In more detail, this moves the local state of the connection to2605 the CLOSED state and triggers a close frame to be sent to the2606 peer. A connection is fully closed once both peers have closed it.2607 """2608self._update_cond()2609pn_connection_close(self._impl)2610ifhasattr(self,'_session_policy'):2611# break circular ref2612delself._session_policy

2616"""2617 The state of the connection as a bit field. The state has a local2618 and a remote component. Each of these can be in one of three2619 states: UNINIT, ACTIVE or CLOSED. These can be tested by masking2620 against LOCAL_UNINIT, LOCAL_ACTIVE, LOCAL_CLOSED, REMOTE_UNINIT,2621 REMOTE_ACTIVE and REMOTE_CLOSED.2622 """2623returnpn_connection_state(self._impl)

2731"""2732 A representation of an AMQP link, of which there are two concrete2733 implementations, Sender and Receiver.2734 """27352736SND_UNSETTLED=PN_SND_UNSETTLED2737SND_SETTLED=PN_SND_SETTLED2738SND_MIXED=PN_SND_MIXED27392740RCV_FIRST=PN_RCV_FIRST2741RCV_SECOND=PN_RCV_SECOND27422743@staticmethod

2771"""2772 Opens the link.27732774 In more detail, this moves the local state of the link to the2775 ACTIVE state and triggers an attach frame to be sent to the2776 peer. A link is fully active once both peers have attached it.2777 """2778pn_link_open(self._impl)

2781"""2782 Closes the link.27832784 In more detail, this moves the local state of the link to the2785 CLOSED state and triggers an detach frame (with the closed flag2786 set) to be sent to the peer. A link is fully closed once both2787 peers have detached it.2788 """2789self._update_cond()2790pn_link_close(self._impl)

2794"""2795 The state of the link as a bit field. The state has a local2796 and a remote component. Each of these can be in one of three2797 states: UNINIT, ACTIVE or CLOSED. These can be tested by masking2798 against LOCAL_UNINIT, LOCAL_ACTIVE, LOCAL_CLOSED, REMOTE_UNINIT,2799 REMOTE_ACTIVE and REMOTE_CLOSED.2800 """2801returnpn_link_state(self._impl)

3039"""3040 Send specified object over this sender; the object is expected to3041 have a send() method on it that takes the sender and an optional3042 tag as arguments.30433044 Where the object is a Message, this will send the message over3045 this link, creating a new delivery for the purpose.3046 """3047ifhasattr(obj,'send'):3048returnobj.send(self,tag=tag)3049else:3050# treat object as bytes3051returnself.stream(obj)

3237"""3238 Set the local state of the delivery e.g. ACCEPTED, REJECTED, RELEASED.3239 """3240obj2dat(self.local._data,pn_disposition_data(self.local._impl))3241obj2dat(self.local._annotations,pn_disposition_annotations(self.local._impl))3242obj2cond(self.local._condition,pn_disposition_condition(self.local._impl))3243pn_delivery_update(self._impl,state)

3278"""3279 Settles the delivery locally. This indicates the application3280 considers the delivery complete and does not wish to receive any3281 further events about it. Every delivery should be settled locally.3282 """3283pn_delivery_settle(self._impl)

3291"""3292 Aborts the delivery. This indicates the application wishes to3293 invalidate any data that may have already been sent on this delivery.3294 The delivery cannot be aborted after it has been completely delivered.3295 """3296pn_delivery_abort(self._impl)