From 21161981b5a708b521afd9348983963407f8d7dd Mon Sep 17 00:00:00 2001 From: Kenneth Giusti Date: Fri, 14 Mar 2014 12:35:34 -0400 Subject: [PATCH] Update documentation. --- docs/User-Guide.md | 994 +++++++++++++++++++++++++-------------------- 1 file changed, 559 insertions(+), 435 deletions(-) diff --git a/docs/User-Guide.md b/docs/User-Guide.md index ef6e3c9..74eeeba 100644 --- a/docs/User-Guide.md +++ b/docs/User-Guide.md @@ -39,7 +39,6 @@ functionality. [2] Not entirely true - it may be possible to multithread as long as connections are not shared across threads. TBD - ## What this framework doesn't do ## * __Message management__ - All messages are assumed to be Proton @@ -80,16 +79,14 @@ QPID website](http://qpid.apache.org/components/messenger/index.html This framework defines the following set of objects: - * Container - an implementation of the container concept defined by - AMQP 1.0. An instance must have a name that is unique across - the entire messaging domain as it is used as part of the - address. This object is a factory for Connections. + * __Container__ - an implementation of the container concept defined + by AMQP 1.0. This object is a factory for Connections. - * Connection - an implementation of the connection concept defined by + * __Connection__ - an implementation of the connection concept defined by AMQP 1.0. You can think of this as a data pipe between two Containers. This object is a factory for links. - * Links - A uni-directional pipe for messages traveling between + * __Links__ - A uni-directional pipe for messages traveling between resources (nodes) within a container. A link exists within a Connection, and uses the Connection as its data path to the remote. There are two sub-classes of Links: *SenderLinks* and @@ -97,635 +94,762 @@ This framework defines the following set of objects: node. ReceiverLinks consume messages on behalf of a local node. -And application creates one or more Containers, which represents a -domain for a set of message-oriented 'nodes' (queues, publishers, -consumers, etc) offered by the application. +An application creates one or more Containers, which represents a +domain for a set of message-oriented **nodes**. Nodes are those +components within an application that are the source or sink of a +message flow. Example nodes would include message queues, message +topics, a database, an event logger, etc. A node is identified by its +name, which must uniquely identify the node within its container. -The application then forms network connections with other systems that -offer their own containers. The application may initiate these -network connections (eg. call connect()), or listen for connection -requests from remote systems (eg. listen()/accept()) - this is -determined by the application's design and purpose. The method used by -the application to determine which systems it should connect to in -order to access particular resources and Containers is left to the +To pass messages between nodes, the application must first set up a +Connection between the two Containers that hold the nodes. To do +this, the application creates a network connection to the system that +holds the remote Container. How this network connection is created is +determined by the application's design and purpose. For example, the +application may proactively initiate these network connections +(eg. call connect()), or passively listen for connection requests +coming from remote systems (eg. listen()/accept()). The method used +by the application to determine which systems it should connect to in +order to access particular resources (eg. nodes) is left to the application designers. -The application must create a Connection object for each network -connection it has set up. A Connection object is allocated from the -Container, and represents a data pipe between the local and remote -Containers. The Connection consumes data from, and produces data for, -its network connection. It is the responsiblity of the application to -transfer network data between the Connection object and its -corresponding network connection. +The application must then create a Connection object to manage the +network connection it has set up. A Connection object is allocated +from the Container, and represents the data pipe between the local and +remote Containers. The Connection consumes data arriving from, and +produces data for, its network connection. It is the responsiblity of +the application to transfer network data between the Connection object +and its corresponding network connection. -If the application needs to send messages to a node on the remote -Container, it allocates a SenderLink from the Connection that attaches -to that remote Container. The application assigns a local name to the -SenderLink that identifies the node that is the source of the messages -sent over it. This is the Source address, and is made available to -the remote so it may classify the origin of the message stream. The -application may also supply the address of the node to which it is -sending. This is the Target node address. The Target address -supplied by the sender is merely a hint for the remote application - -the remote may override this address, and provide the actual Target -address used by the remote. If no Target address is given, the remote -may allocate one on behalf of the sending application. The +To transfer messages between the connected Container's nodes, a *link* +must be created. A link is uni-directional; from the application's +perspective, it either sends messages to a remote node, or consumes +messages from a remote node. The framework provides two distinct link +classes - one for sending messages to a node, the other for receiving +messages from a node. + +To send messages to a node on the remote Container, the application +allocates a *SenderLink* from the Connection that attaches to that +remote Container. The application assigns a local name to the +SenderLink which identifies the node that is the source of the +messages sent byit. This is the *Source node address*, and is made +available to the remote so it may classify the origin of the message +stream. The application may also supply the address of the node to +which it is sending. This is the *Target node address*. The Target +address supplied by the application is merely a hint for the peer - +the peer may override the supplied address and provide the actual +Target address in use by the peer. If no Target address is given the +remote may allocate one on behalf of the sending application. The SenderLink's final Target address is made available to the sending application once the link has completed setup. When sending a message, an application can choose whether or not it needs to know about the arrival status of the message at the remote -node. The application may send the message as "best effort" if it -doesn't care about the arrival status. This 'send-and-forget' service -provides no feedback on the delivery of the message. Otherwise, the +node. The application may send the message as *best effort* if it +doesn't care about the arrival status. This *send-and-forget* service +provides no feedback on the delivery of the message. Otherwise the application may register a callback that is invoked when the delivery status of the message is determined by the framework. -All messages are sent using 'at-most-once' semantics: the framework +All messages are sent using *at-most-once* semantics: this framework does not attempt to re-send messages on behalf of the application. If -reliable messaging is required, the application must implement its own +reliable messaging is required the application must implement its own retry logic. If the application needs to consume messages from a node on the remote -Container, it allocates a ReceiverLink from the Connection that +Container, it allocates a *ReceiverLink* from the Connection that attaches to that remote Container. The application assigns a local name to the ReceiverLink that identifies the local node that is the consumer of all the messages that arrive on the link. This is the -Target node address, and is made available to the remote so it may -classify the destination of the message stream. The application may +*Target node address*, and is made available to the remote so it may +identify the destination of the message stream. The application may also supply the address of the remote node from which it is consuming. -This is the Source node address. The Source address supplied by the +This is the *Source node address*. The Source address supplied by the receiver is merely a hint for the remote application - the remote may -override this address, and provide the actual Source address used by -the remote. address may be overridden by the remote. If no Source -address is given, the remote may allocate one on behalf of the -receiving application. The ReceiverLink's final Source address is -made available to the receiving application once the link has -completed setup. +override this address and provide the actual Source address used by +the remote. If no Source address is given the remote may allocate one +on behalf of the receiving application. The ReceiverLink's final +Source address is made available to the receiving application once the +link has completed setup. ## Callback Events ## -Callbacks are used by the framework to notify the application when -certain events occur. Callbacks for various events may be associated -with the Connection, SenderLink, and ReceiverLink objects. +This framework uses a callback model to notify the application when +messaging-related events have occurred. Each of the object types +provided by the framework define a set of events that may be of +interest to the application. To receive these events, the application +must register callback handlers with each object that it manages. See +the API section for details regarding each class's event handlers. -### Connection Events ### - -Callbacks can be registered with an instance of a Connection object. -These callbacks are invoked on the following events: - -* __Connection Active__ - The connection has transitioned to the - active state. -* __Connection Closed__ - The connection has cleanly closed. -* __Connection Failed__ - The connection has failed. -* __Connection Remote Closed__ - The peer has initiated the close of - the connection. -* __Sender Requested__ - The peer needs to consume messages from a - node in the local container, and is asking your application to - create a SenderLink on its behalf. The intent of this SenderLink is - to provide messages for the peer to consume. The peer may provide - the Target address of its consuming node and the Source address of - the node it is trying to consume from. -* __Receiver Requested__ - The peer needs to send messages to a node - in the local container and is asking your application to create a - ReceiverLink on its behalf. The intent of this ReceiverLink is to - consume the incoming messages from the peer. The peer may provide - the Source address of its consuming node and the Target address of - the node it is trying to consume from. -* __SASL Step__ - TBD: intercept the SASL handshake if SASL used. -* __SASL Done__ - TBD: the result of the SASL handshake. - -See the API section for more detail. - -### SenderLink Events ### - -Callbacks can be registered with an instance of a SenderLink object. -These callbacks are invoked on the following events: - -* __Sender Active__ - The link has transitioned to the active state. -* __Sender Closed__ - The link has cleanly closed. -* __Sender Remote Closed__ - The peer has initiated the close of the - link. -* __Sender Credit Granted__ - The peer has made more credit available - to the sender. - -In addition to the above, a callback can be associated with each -message sent over the SenderLink. This callback is used to signal the -delivery status of the message. - -See the API section for more detail. - -### ReceiverLink Events ### - -Callbacks can be registered with an instance of a ReceiverLink object. -These callbacks are invoked on the following events: - -* __Receiver Active__ - The link has transitioned to the active state. -* __Receiver Closed__ - The link has cleanly closed. -* __Receiver Remote Closed__ - The peer has initiated the close of the - link. -* __Message Received__ - A message has arrived from the peer. - -See the API section for more detail. - -__STOP HERE__ +---------- # API # -## Container ## +## The Container Class ## -`Container( name, containerEventHandler, properties={} )` +The Container class provides a named repository for nodes. It is +identified by a name, which must uniquely identify the Container +across all Containers in the messaging domain. + +TBD: locking - allow thread-per-connection functionality, would need +locking for container management of connections!! + +### Container Methods ### + +`Container(name, containerEventHandler, properties)` Construct a container. Parameters: -* name - identifier for the new container, MUST BE UNIQUE across the -entire messaging domain. -* containerEventHandler - callbacks for container events (see below) -* properties - map, contents TBD +* __name__ - string, an identifier for the new container, __MUST__ be +unique across the entire messaging domain. +* __ContainerEventHandler__ - object, provides callback handlers for + container events (see below) +* __properties__ - map, contents TBD -`Container.create_connection( name, ConnectionEventHandler, properties={}...)` +`Container.create_connection(name, ConnectionEventHandler, properties)` -The factory for Connection objects. Parameters: +The factory for Connection objects. Use this to create a connection to +a peer Container. Your application must create a unique Connection +object for each network connection it makes (eg. per-socket, in the +case of TCP). Parameters: -* name - uniquely identifies this connection within the Container -* properties - map containing the following optional connection +* __name__ - string, name of this Connection. The name __MUST__ uniquely + identify this connection within the Container - no two Connections + within a Container can share the same name. +* __ConnectionEventHandler__ - object, provides callback handlers for the + new Connection (see below). +* __properties__ - map containing the following optional connection attributes: - * "remote-hostname" - DNS name of remote host. - * "idle-time-out" - time in milliseconds before connection is - closed due to lack of traffic. Setting this may enable heartbeat - generation by the peer, if implemented. - * "sasl" - map of sasl configuration stuff (need callbacks, TBD) - * "ssl" - ditto, future-feature + * "hostname" - string, DNS name of __remote__ host (ie. the host + that is being connected to). This name will also be used by the + SSL layer to check the CommonName/SAN contained in the + certificate provided by the peer. + * "idle-time-out" - integer, time in seconds before the Connection + is closed due to lack of traffic. Setting this may enable + heartbeat generation by the peer, if supported. + * "x-trace-protocol" - boolean, if True, enable debug dumps of the + AMQP wire traffic. + * "x-ssl-ca-file" - string, path to a PEM file containing the + certificates of the trusted Certificate Authorities that will be + used to check the signature of the peer's certificate. + * "x-ssl-server" - boolean, if True, the Connection acts as a SSL + server (default False - use Client mode) + * "x-ssl-identity" - tuple, contains self-identifying certificate + information which will be presented to the peer. The first item + in the tuple is the path to the certificate file (PEM format). + The second item is the path to a file containing the private key + used to sign the certificate (PEM format, optional if private key + is stored in the certificate itself). The last item is the + password used to encrypt the private key (string, not required if + private key is not encrypted) + * "x-ssl-verify-mode" - string, configure the level of security + provided by SSL. Possible values: + * "verify-peer" (default) - most secure, requires peer to + supply a certificate signed by a valid CA (see + x-ssl-ca-file), and checks the CN or SAN entry in the + certificate against the expected peer hostname (see + x-ssl-peer-name) + * "verify-cert" (default if no hostname or x-ssl-peer-name + given) - like verify-peer, but skips the check of the peer + hostname. Vulnerable to man-in-the-middle attack. + * "no-verify" - do not require the peer to provide a + certificate. Results in a weaker encryption stream, and + other vulnerabilities. + * "x-ssl-peer-name" - string, DNS name of peer. Can be used to + override the value passed in by the "hostname" option, if + necessary. A DNS host name is required to authenticate peer's + certificate (see x-ssl-verify-mode). + * "x-ssl-allow-cleartext" - boolean, allows clients to connect + without using SSL (eg, plain TCP). Used by a server that will + accept clients requesting either trusted or untrusted + connections. +`Container.name()` -`Container.need_io()` +Returns the name of the Container. - Returns a pair of lists containing those connections that are read blocked and write-ready. +`Container.need_processing()` +A utility to help determine which Connections need processing. Returns +a triple of lists containing those connections that: -`Container.next_tick()` + * need to read from the network (index 0) + * need to write to the network (index 1) + * waiting for their *next-tick* timer to expire (see *Connection.process()*). (index 2) -Return the timestamp of the next pending timer event to expire. In -seconds since Epoch. Your application must call Container.process_tick() -at least once at or before this timestamp expires! +The timer list is sorted with the Connection next expiring at index 0. +`Container.get_connection(name)` -`Container.process_tick(now)` +Returns the Connection instance identified by *name*. -Does all timer related processing for all of the Connections held by -this Container. Returns a list of all the Connections which had -timers expire. You must call `Container.process_tick()` after this -call to determine the deadline for the next call to `process_tick()` -should be made. +### Container Events ### +The ContainerEventHandler passed on container construction has the +following callback methods that your application can register: -`Container.resolve_sender(target-address)` +**TBD** - At this point, I've got none defined. -Find the SenderLink that sends to the remote resource with the address -*target-address* +## The Connection Class ## +A Connection is created from the Container that it is going to +'connect'. See the *create_connection()* Container method. -`Container.resolve_receiver(source-address)` +`Connection.name()` -Find the ReceiverLink that consumes from the remote resource with the -address *source-address* +Returns the name of the Connection. +`Connection.remote_container()` -`Container.get_connection(connection-name)` +Returns the name of the remote container. This name is only available +once the Connection has become Active. -Return the Connection identified by +`Connection.user_context` +A opaque handle that can be set by the application for its own +per-Connection data. -### ContainerEventHandler ### +`Connection.open()` -The ContainerEventHandler passed on container construction has the following callback methods that your application can register: +Initiate the connection to the remote peer. This must be called in +order to transfer data over the Connection. The Connection is +considered active once both peers have opened it. -**TBD** +`Connection.close()` +Terminate the connection to the remote peer. This should be called +when the application is done with the Connection and wants to perform +a clean close. The Connection is considered closed when both peers +have closed it. -## Connection ## +`Connection.closed()` -No public constructor - use Container.create_connection(). +True when both peers have completed closing the Connection. +`Connection.destroy()` -`Connection.tick(now)` +This releases the Connection and all links that use the connection. +This must be called to release the resources used by the Connection. +Once called the Connection is no longer present - the application +should drop all references to the destroyed Connection. -Updates any protocol timers running in the connection, and returns the expiration time of the next pending timer. - -* now: seconds since Epoch -* returns: a timestamp, which is the deadline for the next expiring timer in seconds since Epoch. Zero if no active timers. +`Connection.process(now)` +This causes the Connection to run the AMQP protocol state machine. +This method must be called periodically (see *Connection.next_tick*) +and whenever network I/O has been done on the connection (see below). +Event callbacks may occur when this method is invoked. The *now* +parameter is the current time (format determined by the platform). +This method returns a timestamp which is the maximum time interval the +application can wait before it must call Connection.process() again. If +Connection.process() is not called at or before this deadline the +Connection may fail. `Connection.next_tick()` -Returns the last value returned from the `Connection.tick()` call. - +Returns the deadline for the next call to Connection.process(). This +is the same value that was returned by the last call to `Connection.needs_input()` -Returns the number of bytes of inbound network data this connection -can process. Returns zero if no input can be processed at this time. -Returns `EOS` when the input pipe has been closed. - +Returns the number of bytes of inbound network data this Connection is +capable of consuming. Returns zero if no input can be processed at +this time. Returns `EOS` when the input pipe has been closed. `Connection.process_input(data)` Process data read from the network. Returns the number of bytes from `data` that have been processed, which will be no less than the last value returned from `Connection.need_input()`. Returns EOS if the -input pipe has been closed. - +input pipe has been closed. The application should call +Connection.process() after calling this method. `Connection.input_closed(reason)` -Indicates to the framework that the read side of the network -connection has closed. - +The application must call this method when the inbound network data +source has closed. This indicates that no more data arrive for this +Connection. The application should call Connection.process() after +calling this method. `Connection.has_output()` -Returns the number of bytes of output data the connection has +Returns the number of bytes of output data the Connection has buffered. This data needs to be written to the network. Returns zero when no pending output is available. Returns EOS when the output pipe -has been closed. - +has been closed. The application should call Connection.process() +prior to calling this method. `Connection.output_data()` Returns a buffer containing data that needs to be written to the network. Returns None if no data or the output pipe has been closed. - `Connection.output_written(N)` -Indicate to the framework that N bytes of output data (as given by -`Connection.output_data()`) has been written to the network. This -will cause the framework to release the first N bytes from the buffer -output data - allowing the framework to generate more output. +The application must call this to notify the framework that N bytes of +output data (as given by `Connection.output_data()`) has been written +to the network. This will cause the framework to release the first N +bytes from the buffer output data. +`Connection.output_closed()` -`Connection.output_closed(reason)` +The application must call this method when the outbound network data +pipe has closed. This indicates that no more data can be written to +the network. -Indicates to the framework that the write side of the network -connection has closed. +`Connection.create_sender(source_address, target_address, + SenderEventHandler, name, properties)` -`Connection.destroy(error=None)` +Construct a SenderLink over this Connection which will send messages +to the node identified by *target_address* on the remote. If +*target_address* is None the remote may create a node for this link. +The target address of a dynamically-created node will be made +available via the SenderLink once the link is active. Parameters: -Close the network connection, and force any in-progress message -transfers to abort. Deletes the Connection (and all underlying Links) -from the Container. The socket is closed as a result of this method. -Parameters: -* error - optional error, supplied by application if closing due to an unrecoverable error. - - -`Connection.create_sender( source-resource, target-resource=None, - senderEventHandler, properties={})` - -Construct a SenderLink using this connection which will send messages -to the *target-resource* on the remote. If *target-resource* is None, -the remote may generate one. The address of a dynamically-created -Target will be made available via the SenderLink once the link is -active. Parameters: - -* source-resource - resource address of the local resource that is - generating the messages sent on this link. This address may be - prefixed with the local containter name. -* target-resource - resource address of the destination resource that - is to consume the sent messages. May be None if the remote can - dynamically allocate a resource for the target. The resource - address may be prefixed with the remote container name. -* senderEventHandler - a set of callbacks for monitoring the state of +* **source_address** - string, address of the local node that is + generating the messages sent on this link. +* **target_address** - string or None, address of the destination node + that is to consume the sent messages. May be None if the remote can + dynamically allocate a node for consuming the messages. +* __SenderEventHandler__ - a set of callbacks for monitoring the state of the link. See below. -* properties - map of optional properties *TBD* +* __name__ - string, optional name for the created link, __MUST__ be + unique across all SenderLinks on this Connection. +* __properties__ - map of optional properties to apply to the link: + * "distribution-mode" - informs the receiver of the distribution + mode of messages supplied by this link (see the AMQP 1.0 + specification for details). Values: + * "move" - the message will not be available for other consumers + once it has been accepted by the remote. This implies that a + message will be consumed by only one consumer. + * "copy" - the message will continue to be available for other + consumers after it has been accepted by the peer. This implies + that multiple consumers may get a copy of the same message. + +`Connection.accept_sender(handle, source_override, SenderEventHandler, properties)` + +This constructs a SenderLink in response to a request from the peer to +consume from a node. When a peer wants to consume messages from a +local node it will request that the application create a SenderLink +on its behalf. This SenderLink will be used to transfer the messages +to the peer. The application is notified of such a request via the +*sender_requested* Connection callback (see below). After receiving +this notification the application may grant the request by calling +this method. Parameters: + +* __handle__ - opaque handle provided by the + Connection.sender_requested() callback. This handle is used by the + framework to correlate the created SenderLink with the request from + the peer. +* **source_override** - string, the address of the source node. This + allows the application to supply (or override) the source address + requested by the peer. +* __SenderEventHandler__ - object containing callbacks for events + generated by this SenderLink (see below). +* __properties__ - map of properties used by the SenderLink. Same + values as supplied to the *create_sender* method. Values in this + map will override any properties requested by the peer. + +`Connection.reject_sender(handle, reason)` + +Called by the application to reject a request from the peer to create +a SenderLink. This should be called instead of *accept_sender()* if +the application wants to deny the peer's request. The application is +notified of such a request via the *sender_requested* Connection +callback (see below). Parameters: + +* __handle__ - the opaque handle provided by the + *Connection.sender_requested()* callback. +* __reason__ - **TBD** -`Connection.accept_sender(sender-info, ... TBD)` +`Connection.create_receiver( target_address, source_address, + ReceiverEventHandler, name, properties)` -Accept a remotely-requested SenderLink and construct it (see the -ConnectionEventHandler.sender_request() method below). +Construct a ReceiverLink over this Connection which will consume +messages from the node identified by *source_address* on the remote. +If *source_address* is None the remote may create a node for this +link. The source address of the dynamically-created node will be made +available via the ReceiverLink once the link is active. Parameters: - -`Connection.reject_sender(sender-info, reason, ... TBD)` - -Reject a remotely-requested SenderLink (see the -ConnectionEventHandler.sender_request() method below) - - -`Connection.create_receiver( target-resource, source-resource=None, - receiverEventHandler, properties={})` - -Construct a ReceiverLink using this connection which will consume -messages from the *source-resource* on the remote. If -*source-resource* is None, the remote may generate one. The address -of the dynamically-created Source will be made available via the -ReceiverLink once the link is active. Parameters: - -* target-resource - resource address of the local resource that is +* **target_address** - string address of the local node that is consuming the messages arriving on the link. -* source-resource - resource address of the remote resource that is - generating the messages arriving on the link. May be None if the - remote can dynamically allocate a resource for the source. The - resource address may be prefixed with the remote container name. -* receiverEventHandler - a set of callbacks for receiving messages and - monitoring the state of the link. See below. -* properties - map of optional properties, including: - * capacity - maximum number of incoming messages this receiver can - buffer. +* **source_address** - string or None, address of the remote node that is + to supply the messages arriving on the link. May be None if the + remote can dynamically allocate a node for the source. +* __receiverEventHandler__ - object containing a set of callbacks for + receiving messages and monitoring the state of the link. See below. +* __properties__ - map of optional properties to apply to the link: + * "distribution-mode" - Requests the distribution mode that the + peer's SenderLink should use when supplying messages. This is + merely a request and can be overridden by the peer. Values are + the same as given for *Connection.create_sender()* -`Connection.accept_receiver(receiver-info, ... TBD)` +`Connection.accept_receiver(handle, target_override, ReceiverEventHandler, + properties)` -Accept a remotely-requested ReceiverLink and construct it (see the -ConnectionEventHandler.receiver_request() method below). +This constructs a ReceiverLink in response to a request from the peer +to send messages to a node. When a peer wants to send messages to a +local node it will request that the application create a ReceiverLink +on its behalf. This ReceiverLink will be used to consume the messages +sent by the peer. The application is notified of such a request via +the *receiver_requested* Connection callback (see below). After +receiving this notification the application may grant the request by +calling this method. Parameters: +* __handle__ - opaque handle provided by the + Connection.receiver_requested() callback. This handle is used by the + framework to correlate the created ReceiverLink with the request from + the peer. +* __target_override__ - string, the address of the target node. This + allows the application to supply (or override) the target address + requested by the peer. +* __ReceiverEventHandler__ - object containing callbacks for events + generated by this ReceiverLink (see below). +* __properties__ - map of properties used by the ReceiverLink. **TBD** -`Connection.reject_receiver(receiver-info, reason)` +`Connection.reject_receiver(handle, reason)` -Reject a remotely-requested ReceiverLink (see the -ConnectionEventHandler.sender_request() method below) +Called by the application to reject a request from the peer to create +a ReceiverLink. This should be called instead of *accept_receiver()* +if the application wants to deny the peer's request. The application +is notified of such a request via the *receiver_requested* Connection +callback (see below). Parameters: +* __handle__ - the opaque handle provided by the + *Connection.receiver_requested()* callback. +* __reason__ - **TBD** -### ConnectionEventHandler ### +### Connection Events ### -The ConnectionEventHandler passed on connection construction has the -following callback methods that your application can register: +Callbacks can be registered with an instance of a Connection object. +These callbacks are invoked on the following events: +* The Connection becomes active. +* The peer has requested that the Connection be closed. +* The Connection has closed. +* The Connection has experienced a failure. +* The peer wants to consume from a local node. +* The peer wants to send messages to a local node. +* SASL authentication -`ConnectionEventHandler.connection_active(connection)` +Callbacks for these events are provided by the application via the +ConnectionEventHandler object. The following callbacks are defined +for a Connection: -Called when the connection transitions to up. +`connection_active(Connection)` -* connection - the Connection +The Connection has transitioned to the Active state. This means that +both ends of the Connection can send and receive data. +`connection_closed(Connection)` -`ConnectionEventHandler.connection_closed(connection, error-code)` +The Connection has closed cleanly. This event is generated as a +result of both ends of the Connection being closed via the *close()* +method. -Called when connection has been closed by peer. Error-code provided -by peer (optional). +`connection_remote_closed(Connection, error)` -* connection - the Connection +Indicates that the peer has issued a *close()* on the connection. **TBD** error +`connection_failed(Connection, error)` -`ConnectionEventHandler.receiver_request(connection, source-resource, - target-resource, receiver-info, ...)` +Indicates that the connection has failed. No further message passing +is possible and all contained links are dead. At this point the +application has no choice but to destroy the Connection. **TBD** error -The peer is attempting to create a new ReceiverLink so it can -send messages to a resource in the local container. This resource is -identified by *target-resource*. Your application must accept or -reject this request. If *target-resource* is None, the peer is -requesting your application generate a resource - your application -must provide the address of this resource should you accept this -ReceiverLink. Parameters: +`sender_requested(Connection, handle, name, requested_source, properties)` -* connection - the Connection -* source-resource - the address of the remote resource that will - generate the arriving messages. -* target-resource - the requested address of the local resource that - will be consuming the inbound messages. May be overridden by the - application. -* receiver-info *TBD* +The peer has requested that a SenderLink be created so it can consume +messages from a node in the local Container. The *requested_source* is +the address of the (source) node that the peer wishes to consume +messages from. The application may accept the request by calling +*Connection.accept_sender()* or deny the request by calling +*Connection.reject_sender()* +`receiver_requested(Connection, handle, name, requested_target, properties)` -`ConnectionEventHandler.sender_request( connection, target-resource, - source-resource, sender-info, ...)` +The peer needs to send messages to a node in the local container and +is asking your application to create a ReceiverLink on its behalf. +The intent of this ReceiverLink is to consume the incoming messages +from the peer. The *requested_target* is the address of the (target) +node that the peer wishes to send messages to. The application may +accept the request by calling *Connection.accept_receiver()* or deny +the request by calling *Connection.reject_receiver()* -The peer is attempting to create a new SenderLink so it can consume -messages from a resource in the local container. This resource is -identified by *source-resource*. Your application must accept or -reject this request. If *source-resource* is None, the peer is -requesting your application generate a resource - your application -must provide the address of this resource should you accept this -SenderLink. +`sasl_step(Connection, pn_sasl)` -* connection - the Connection -* target-resource - the address of the remote resource that will - consume the arriving messages. -* source-resource - the requested address of the local resource that - will be generating the outbound messages. May be overridden by the - application. -* sender-info *TBD* +Invoked each time the SASL negotiation transfers information. See the +Proton API for more detail. +`sasl_done(Connection, result)` -**TBD - what about SASL result?** +Invoked on completion of the SASL handshake. See the Proton API for +more detail. -**TBD - what about SSL (if not already provided with socket)?** +## The SenderLink Class ## +A SenderLink is created from the Connection that connects to remote +Container that holdes the target node. See the +*Connection.create_sender()* and *Connection.accept_sender()* methods. +`SenderLink.name()` -## SenderLink ## +Returns the name of the SenderLink. -No public constructor - use Connector.create_sender() for creating a -local sender or `Connector.accept_sender()` to establish a -remotely-requested one. +`SenderLink.user_context` -`SenderLink.send( Message, DeliveryCallback=None, handle=None, deadline=None )` +A opaque handle that can be set by the application for its own +per-SenderLink data. + +`SenderLink.open()` + +A SenderLink must be opened before it will entry the Active state and +messages can be sent. + +`SenderLink.source_address()` + +Returns the address of the local node that is the source of the sent messages. + +`SenderLink.target_address()` + +Returns the address of the node in the peer's Container that will +accept the sent messages. Note that this address is not final until +the SenderLink has reached the Active state. + +`SenderLink.close()` + +Initiate a close of the SenderLink. + +`SenderLink.closed()` + +Returns True when the SenderLink has closed. + +`SenderLink.destroy()` + +This releases the SenderLink. This must be called to release the +resources used by the SenderLink. Once called the SenderLink is no +longer present - the application should drop all references to the +destroyed SenderLink. + +`SenderLink.send(message, delivery_callback, handle, deadline)` Queue a message for sending over the link. *Message* is a Proton Message object. If there is no need to know the delivery status of -the message at the peer, then DeliveryCallback, handle, and deadline +the message at the peer then *delivery_callback*, *handle*, and *deadline* should not be provided. In this case, the message will be sent -"pre-settled". To get notification on the delivery status of the -message, a callback and handle must be supplied. The deadline is -optional in this case. This method returns 0 if the message was -queued successfully (and the callback, if supplied, is guaranteed to -be invoked). Otherwise the message was not queued and no callback -will be made. Parameters: - -* Message - a complete Proton Message object -* handle - opaque object supplied by application. Passed to - DeliveryCallback method. -* deadline - future timestamp when send should be aborted if not - completed. In seconds since Epoch. -* DeliveryCallback( SenderLink, handle, status, reason=None ) - - optional, invoked when the send operation completes. The status - parameter will be one of: - * TIMED_OUT - send did not complete before deadline hit, send aborted (locally generated) - * ACCEPTED - remote has received and accepted the message - * REJECTED - remote has received but has rejected the message - * RELEASED - see 'ReceiverLink.message_released()` - * MODIFIED - see 'ReceiverLink.message_modified()` - * ABORTED - connection or sender has been forced closed/destroyed, - etc. (locally generated) In this case, the reason parameter may be set to an error - code. - * UNKNOWN - the remote did not provide a delivery status. +*pre-settled*. To get notification on the delivery status of the +message a *delivery_callback* and *handle* must be supplied. The +*deadline* is optional in this case. This method returns 0 if the +message was queued successfully (and the *delivery_callback*, if +supplied, is guaranteed to be invoked). Otherwise an error occurred +and the message was not queued and no callback will be made. +Parameters: +* __message__ - a complete Proton Message object +* __handle__ - opaque object supplied by application. Passed to + the *delivery_callback* method. +* __deadline__ - future timestamp when the send should be aborted if + it has not completed. In seconds since Epoch. +* **`delivery_callback`** - an optional method that will be invoked when + the delivery status of the message has reached a terminal state. + The callback accepts the following parameters: + * __SenderLink__ - the link over which the message was sent. + * __handle__ - the handle provided in the *send()* call. + * __status__ - the status of the delivery. It will be one of the + following values: + * `TIMED_OUT` - the delivery did not reach a terminal state + before the deadline expired. Whether or not the message was + actually received is unknown. + * `ACCEPTED` - the remote has received and accepted the message. See `ReceiverLink.message_accepted()` + * `REJECTED` - the remote has received but has rejected the message. See `ReceiverLink.message_rejected()` + * `RELEASED` - the remote has received but will not accept the message. See `ReceiverLink.message_released()` + * `ABORTED` - Connection or SenderLink has been + closed/destroyed/failed, etc. + * `UNKNOWN` - the remote did not provide a delivery status. + * `MODIFIED` - **RESERVED** **TBD** + * __error__ - if status is ABORTED, an error code is provided **TBD** + * __outcome__ - **RESERVED** **TBD** `SenderLink.pending()` Returns the number of outging messages in the process of being sent. - `SenderLink.credit()` Returns the number of messages the remote ReceiverLink has permitted the SenderLink to send. +`SenderLink.flushed()` **TBD** -`SenderLink.destroy(error)` +### SenderLink Events ### -Close the link, and force any in progress message transfers to abort. -Deletes the SenderLink from the Container. Parameters: +Callbacks can be registered with an instance of a SenderLink object. +These callbacks are invoked on the following events: -* error - optional error, supplied by application if closing due to an - unrecoverable error. +* The link becomes active. +* The peer has initiated the close of the link. +* The link has closed. +* The peer has made credit available to the sender. +Callbacks for these events are provided by the application via the +SenderEventHandler objects. The following callback methods are defined +for a SenderLink: -### SenderEventHandler ### +`sender_active(SenderLink)` -The SenderEventHandler can be passed to the SenderLink's constructor, and has the -following callback methods that your application can register: +Called when the link open has completed and the SenderLink is active. +`sender_closed(SenderLink)` -`SenderEventHandler.sender_active(SenderLink)` +Called when SenderLink has closed. -Called when the link protocol has completed and the SenderLink is active. +`sender_remote_closed(SenderLink, error)` +Indicates that the peer has issued a *close()* on the link. **TBD** error -`SenderEventHandler.sender_closed(SenderLink, error-code)` +`credit_granted(SenderLink)` -Called when connection has been closed by peer, or due to close of the -owning Connection. Error-code provided by peer (optional) +Indicates that the peer has made credit available. The current credit +value can be determined via the *SenderLink.credit()* method. **TBD** +- invoked only when credit transitions from <= 0 to > 0??? +`flush(SenderLink)` **TBD** -## ReceiverLink ## +## The ReceiverLink Class ## -No public constructor - use Connector.create_receiver() for creating a -local receiver or `Connector.accept_receiver()` to establish a -remotely-requested one. +A ReceiverLink is created from the Connection that connects to the +remote Container which holds the source node. See the +*Connection.create_receiver()* and *Connection.accept_receiver()* +methods. +`ReceiverLink.name()` + +Returns the name of the ReceiverLink. + +`ReceiverLink.user_context` + +A opaque handle that can be set by the application for its own +per-ReceiverLink data. + +`ReceiverLink.open()` + +A ReceiverLink must be opened before it will entry the Active state and +messages can be sent. + +`ReceiverLink.source_address()` + +Returns the address of the node in the peer's Container that is the +source of received messages. Note that this address is not final +until the ReceiverLink has reached the Active state. + +`ReceiverLink.target_address()` + +Returns the address of the local node that will accept the received +messages. + +`ReceiverLink.close()` + +Initiate a close of the ReceiverLink. + +`ReceiverLink.closed()` + +Returns True when the ReceiverLink has closed. + +`ReceiverLink.destroy()` + +This releases the ReceiverLink. This must be called to release the +resources used by the ReceiverLink. Once called the ReceiverLink is no +longer present - the application should drop all references to the +destroyed ReceiverLink. `ReceiverLink.capacity()` Returns the number of messages the ReceiverLink is able to queue locally before back-pressuring the sender. Capacity decreases by one -each time a Message is consumed. - +each time a message arrives. Capacity is initialized to zero when the +ReceiverLink is first created - the application must call +*add_capacity()* in order to allow the peer to send messages. `ReceiverLink.add_capacity(N)` -Increases capacity by N messages. Must be called by application to -replenish credit as messages arrive. +Increases the credit made available to the peer by N messages. Must +be called by application to replenish the sender's credit as messages +arrive. +`ReceiverLink.flush()` **TBD** -`ReceiverLink.message_accepted( msg-handle )` +`ReceiverLink.message_accepted( handle )` -Indicate to the remote that the message identified by msg-handle has -been successfully processed by the application (See -ReceiverEventHandler below). +Indicate to the remote that the message identified by *handle* has +been successfully processed by the application. See the +*message_received* callback below, as well as the *SenderLink.send()* +method. +`ReceiverLink.message_rejected( handle, outcome )` -`ReceiverLink.message_rejected( msg-handle, reason )` +Indicate to the remote that the message identified by *handle* is +considered invalid and cannot be processed by the application. See the +*message_received* callback below, as well as the *SenderLink.send()* +method. Outcome **TBD** -Indicate to the remote that the message identified by msg-handle is -considered invalid by the application and has been rejected (See -ReceiverEventHandler below). +`ReceiverLink.message_released( handle )` +Indicate to the remote that the message identified by *handle* will +not be processed by the application and should be made available for +other consumers. See the *message_received* callback below, as well as +the *SenderLink.send()* method. -`ReceiverLink.message_released( msg-handle, reason )` +`ReceiverLink.message_modified( handle, outcome )` -Indicate to the remote that the message identified by msg-handle will -not be processed by the application (See ReceiverEventHandler below). +Indicate to the remote that the message identified by *handle* was +modified by the application but not processed. See the +*message_received* callback below, as well as the *SenderLink.send()* +method. Outcome **TBD** +### ReceiverLink Events ### -`ReceiverLink.message_modified( msg-handle, reason )` +Callbacks can be registered with an instance of a ReceiverLink object. +These callbacks are invoked on the following events: -Indicate to the remote that the message identified by msg-handle was -modified by the application, but not processed (See -ReceiverEventHandler below). +* The link has become active. +* The peer has initiated the close of the link. +* The link has closed. +* A message has arrived from the sender. +Callbacks for these events are provided by the application via the +ReceiverEventHandler objects. The following callback methods are +defined for a ReceiverLink: -`ReceiverLink.destroy(error)` +`receiver_active(ReceiverLink)` -Close the link, terminating any further message deliveries. Deletes the ReceiverLink from the Container. Parameters: +Called when the link open has completed and the ReceiverLink is +active. -* error - optional error, supplied by application if closing due to an - unrecoverable error. +`receiver_closed(ReceiverLink)` +Called when ReceiverLink has closed. -### ReceiverEventHandler ### +`receiver_remote_closed(ReceiverLink, error)` -Passed to ReceiverLink constructor. Has the following callback -methods that your application can register: +Indicates that the peer has issued a *close()* on the link. **TBD** error +`message_received(ReceiverLink, Message, handle)` -`ReceiverEventHandler.receiver_active(ReceiverLink)` +Called when a Proton Message has arrived on the link. Use *handle* to +indicate whether the message has been accepted or not by calling the +appropriate method (*message_accepted*, *message_rejected*, etc) The +capacity of the link will be decremented by one on return from this +callback. Parameters: -Called when the link protocol has completed and the ReceiverLink is active. - - -`ReceiverEventHandler.receiver_closed(ReceiverLink, error-code)` - -Called when connection has been closed by peer, or due to close of the -owning Connection. Error-code provided by peer (optional) - - -`ReceiverEventHandler.message_received(ReceiverLink, Message, msg-handle)` - -Called when a Proton Message has arrived on the link. Use msg-handle -to indicate whether the message has been accepted or rejected by -calling `ReceiverLink.accept_message()` or `ReceiverLink.reject_message()` -as appropriate. The capacity of the link will be decremented by one -on return from this callback. Parameters: - -* ReceiverLink - link which received the Message -* Message - a complete Proton Message -* msg-handle - opaque handle used by framework to coordinate the +* __ReceiverLink__ - link which received the Message +* __Message__ - a complete Proton Message +* __handle__ - opaque handle used by framework to coordinate the message's receive status. - -## ResourceAddress ## - -**TBD: this needs more thought** - -The address for a resource is comprised of four parts: - -* *transport address* - identifies the host of the Container on the - network. Typically this is the DNS hostname, with optional port. -* *container identifier* - the identifier of the Container as - described above. This is represented by a string, and must be - unique across the messaging domain. -* *resource identifier* - the identifer of a resource within the - Container. Represented as a string value. -* property map - an optional map of address properties TBD - -The ResourceAddress can be represented in a string using the following syntax: - - *amqp://[user:password@]//[; {property-map}* - -where: - -* [user:password@] - used for authentication -* transport-address - a DNS hostname. Largely ignored by this - framework, as socket configuration is provided by the application. -* container-id - string, not containing '/' character. The framework - will use this for a part of the Target and Source resource - address. -* resource-id - string, not containing ';' character. The framework - will use this when creating Target and Source addresses for - resources. -* property-map - TBD - -Example: - - "amqp://localhost.localdomain:5672/my-container/queue-A ; {mode: browse}" - -When creating local Target and Source resources, this framework will -assign an address that will be used to identify these resources within -the messaging domain. The resource address will be a string using the -following format: - - /container-id/resource-id - -These strings will be used to set the Target and Source address fields -in the link Attach frame as described by the AMQP 1.0 standard for -locally-maintained resources. The format and syntax of resources -maintained by the peer may not be defined by this framework. This -framework will make no attempt to parse such remotely generated -resource addresses - they will be treated simply as opaque string -values. +`remote_flushed(ReceiverLink)` **TBD** -For the most part, *transport-address* is ignored by the infrastructure. -