This document is still in it's early definition stages.
XATP is intended to be used as a very lightweight and flexible transport protocol that can meet the requirements for most modern Internet application-to-application communications. XATP does not define any routing, content typing, or identification, but instead allows such things to be defined by the applications. By enabling those to be defined at a higher layer, XATP is well suited for building application infrastructure that can quickly adapt and evolve on top of a common shared transport.
XML - XML 1.0 Recommendation
Stream - A single XML document being sent as the only data over a single TCP socket
Namespace - XML Namespaces Recommendation
XIB - Binary data support as defined in the XIB specification
Application - Software sending or receiving Packets in one or more Namespaces
Root - The Stream document root element, parent of all Packets
Packet - Any element in the Stream that is the direct descendent of the Root
Engine - The software processing a Stream and delivering Packets to the Applications
Declared - When a Namespace is specified on the Root, enabling the potential for a Packet in that Namespace
XATP consists of n+ Applications independently communicating with each other over a Stream. This Stream is managed by a simple Engine that processes Packets and Namespaces for the Applications.
The Engine must process Packets from the Stream, and deliver them to the Application that is associated with their Namespace. All Applications must have the option to be made aware by the Engine of changes in the state (connect, error, close, disconnect) of any Stream when their Namespace is Declared. All Engines must support UTF8 encoded Streams [ref], and may optionally support additional encodings. The Engine may support initiating outgoing Streams, accepting incoming Streams, or both.
Every TCP socket contains two Streams, one in each direction. The Engine initiating the socket also initiates the Stream by sending the first Root, then waiting until the receiving Engine sends it's Root. Streams may have long lifetimes, from seconds to days or more, depending on the Application. A Stream is properly terminated by closing the Root element, after which the Stream in the other direction should also properly terminate and the socket is closed.
Todays networks are very diverse, with a wide array of tools being used to manage the traffic across them. XATP enables the tools and devices that manage the network with a header that identifies the content most relevant to making administrative decisions. All XATP Streams can be identified in the first four bytes, which must match "XATP". Version support identified with the major.minor after the separating "/", default being "XATP/1.0", usage like HTTP. All end-point identification and access control on connecting streams can use the host name following the XATP identifier and a single space. Many uses by proxies, application virtual hosting, redirection, and firewalls. Smart proxies and firewalls can scan or parse root block for restricted Namespaces (replace with whitespace to limit), even start alternate streams (partial redirect) or process certain namespaces locally (caching).
XATP/1.0 foobar 80 <stream:stream xmlns:stream="http://xatp.org/ns/1.0#bin" xmlns="http://foobar/">
Not all programming languages and/or XML Parsers are fully equipped to deal efficiently with the requirements of parsing a continually generated streamed XML document. XATP allows accelerated parsing, an alternate method of interpreting the Stream. Every packet is preceded by a string integer and newline, representing the number of bytes in the following packet. To an Engine parsing the Stream as one XML document those acceleration hints are ignored as root level character data. An Engine with the accelerated parsing uses the hint to read an entire packet off of the socket and pass that data to an XML parser as one entire document. Both forms of parsing have their advantages and tradeoffs, and either may be used on the same identical Stream representation. New high performance namespaces can be introduced that take advantage of this to use namespace-specific parsers.
Every Stream begins by sending a Root in the XATP Namespace. The Root must contain all of the Namespace declarations that will be used for any Packet in the Stream. The XATP Namespace does not need to be the default Namespace for the Root, but it must always be declared.
Namespace support is negotiated between the Engines when sending the Root. The sending Engine declares all required and optional Namespaces in it's Root. The receiving Engine declares just the supported subset of the requested Namespaces in it's Root. It is an error if at any time in the Stream a Packet is sent in a Namespace that is not Declared.
Packets are processed by the Engine based on the Namespace of the root element of that Packet. Any other namespaces in a Packet must be qualified directly within the Packet, it is treated as if it were an individual document. It is an error if any elements or attributes within a packet are in a Declared Namespace that is not also qualified locally in the Packet.
The one common required Namespace in a Stream is the XATP Namespace. The XATP Namespace is qualified with the URN of "http://xatp.org/ns/2002/01". This Namespace is the mechanism in which the Root is qualified and the Stream level errors are communicated.
There is a root element named "stream" that must be used at all times for the Root. The one required attribute on the root element is "id" and is always a sufficiently random CDATA with no more than 128 characters. The one optional attribute is "token" and is only used when reconnecting on a new socket while preserving the state of the Stream.
There is a child element named "error" that is used to indicate an error as detected by the Engine in processing the Stream. The error element is always followed by the termination of the Stream. It is used to indicate any processing errors as detected by the Engine, including XML parsing errors and incorrect Namespace usage. The error element optionally contains only CDATA that serves as a more detailed explanation for use when debugging or testing.
The only other child element is named "reconnect" and is used for signaling that the remote Engine should reconnect. Any of the following optional attributes may be specified:
ip - the IP address to reconnect to
port - the port number to reconnect to
wait - a number from 0-255 representing the minimum number of seconds to wait until attempting to reconnect
token - a token that may be used to preserve the state of the Stream upon reconnect
expire - only used in conjunction with a token, a positive integer representing the maximum number of seconds before the token expires
When reconnecting using the token to preserve the state of the Stream, the connecting Engine should send the identical Root, including the exact same Namespaces and id attribute in addition to the given token.
If the Application initiating a connection does not provide the exact IP and port, the Engine must resolve the given host name. Whenever possible, all Engines should first attempt to resolve the given host name with a SRV record of _xatp._tcp.host. If the Engine is incapable of resolving SRV records, the fallback is to resolve an A record of _xatp._tcp.host. Failing the _xatp._tcp.host SRV or A resolutions, the Engine should perform a simple A resolution directly on the host. If there was no port number specified by the Application or provided by the SRV lookup, the default port of 9287 should be used.
To enable the greatest utility to intelligent network tools and to balance with the ease of integration of alternate current or future transport layer encryption methods, all Stream encryption is negotiated. The negotiation is the same as with any other namespace, one or more potential methods may be Declared by the initiator, with the receiver responding only with the supported or chosen method. After the method is negotiated and both stream roots have been sent and received, both sides will initiate the selected method on the socket and the remainder of the stream will be encrypted. This enables firewalls to optionally allow encryption on a by-application or by-method basis. Potential new methods can be easily introduced, and even more intelligent multi-tier methods with intelligent trusted proxies. Engines can still negotiate virtual hosts and application support before negotiating certificates, allowing more manageable secure server platforms.
Whenever possible, all Engines that accept incoming Streams should additionally listen to port 9287 for incoming UDP discovery requests. The Engine should bind to the network broadcast address in addition to any IP it is accepting Streams on. When a discovery request is generated, it should contain all of the Namespaces that are being discovered, and the IP and port if the sender also accepts incoming Streams. When being received and processed, a UDP discovery response should be returned to the senders IP containing the IP and port number the Engine is listening on, as well as the supported subset of the requested Namespaces. One Engine may respond multiple times, possibly representing every alternate virtual host on an IP or to break apart different namespaces into different responses. Responses are always in the same encoding as the request.
When supporting the discovery extension, the Engine should also expose to the Applications the ability to perform or respond to a discovery request. The Engine should allow the Application to specify a small amount of additional character data with it's Namespace in the discovery requests/responses.
<engine xatp="1.0" ip="188.8.131.52" host="foobar" port="1234"> <ns><uri>http://...</uri></ns> <ns><uri>jabber:client</uri><data>jabber.org</data></ns> </engine>
The W3C XML Recommendation http://www.w3.org/TR/REC-xml
XML Namespaces http://www.w3.org/TR/REC-xml-names/
XML Inline Binary http://core.jabber.org/xib.html