Protocol Bindings

Attached below are some thoughts on protocol bindings largely derived from
material in Section 5 of the Abstract Model [6] and discussions with Marc
Hadley and John Ibbotson.

Thoughts and comments welcome.

Best Regards

Stuart Williams
--


XMLP Bindings
-------------
The purpose of an XML Protocol Binding is to provide rules for the transfer
of XML Protocol messages over some specific underlying protocol. The purpose
of a binding architecture is to provide an abstraction so that the core of
the XML protocol can be defined(specified) independently from the definition
(specification) of particular protocol bindings.

 +---------------------------------------+
 |         Core XML Protocol             |
 +---------------------------------------+
 ---------------------------------------- Binding Interface
 +aaaaaaaaa+ +aaaaaaaaa+      +aaaaaaaaa+
 | Nestable| |   P2    |      |   Pn    |
 | Binding | | Binding |......| Binding |
 |aaaaaaaaa+ |         |      |         |
 |   P1    | +yyyyyyyyy+      |         |
 | Binding | |    P2   |      +zzzzzzzzz+
 +xxxxxxxxx+ +---------+      |   Pn    |
 |   P1    |                  +---------+
 +---------+ 

 Fig. 1 Outline Binding Architecture.

Fig. 1 above is based on [1]. The different letter codings at the boundaries
beneath the Binding Interface ("aaaaa") are intended to acknowledge that
each protocol binding, P1, P2,..., Pn is in general specific to that
particular underlying protocol, or more particularly to the services
provided by the underlying protocol. Thus, the P1 binding is specific to the
services of the P1 protocol and so on.

Figure 1 illustrates a single nestable binding that both provides the
binding interface ("aaaa...") at its upper boundary and use the binding
interface at its lower boundary to bind to a protocol binding, P1-Pn, or to
a further nestable binding(s) between itself and an underlying protocol
binding.

The key architectural interface then is the Binding Interface, "aaaaaaaa".
Protocol bindings define convergence or adaption functions that adapt the
behaviour (or services) provided by underlying protocols into the behaviour
(or services) of the Binding Interface. Nestable Bindings act as 'shims'
that are interposed between the top of a protocol binding and the core XML
protocol.

NB: This proposal makes the assumption that the purpose of a binding is to
create a common abstraction across all underlying protocol that 'hides' the
functional differences between different underlying protocols. This common
abstraction is characterised in the definition of a single (abstract)
Binding Interface ("aaaaa..."). This assumption is may not be universally
shared!

Message Exchange Patterns
-------------------------
One of the largest areas for differences in behaviours between underlying
protocols is the message exchange patterns that each naturally supports.
HTTP [2] naturally supports request/response patterns; SMTP [3] naturally
supports a one-way pattern; TCP/IP [4] provides a bi-directional, mutually
asynchronous bytestreams; BEEP [5] provides for more conversational message
patterns - BEEP sessions and channels provide context for extended exchanges
of messages between communicating peers.

There are two broad approaches to the definition of an abstract binding
interface:

1) The interface provides a framework such that a binding can declare what
functionality it supports. Thus not all bindings support all message
patterns. Mechanisms to address common shortcommings can be built-up either
as (shared? - at least in definition) nestable bindings or defined as part
of the core XML protocol. In the worst case an application (a user of the
core XML protocol) needs to be able to adapt its behaviour to suit the
cumulative capabilities of the nested bindings (if any) and the capabilities
of the underlying protocol plus binding.

2) The alternate view is that bindings raise (or reduce) the native
functionality of an underlying protocol to meet some common level of
functionality across all supported protocols. Core XML protocol and
application behaviour is then truely agnostic (from a functional
point-of-view) to the capabilities of a particular underlying protocol. Some
bindings/protocol combinations may be more efficient in certain regards than
others eg. some may directly support the inclusion of binary attachments,
some may intrinsically support the notions of session or request/response.
Nestable bindings may be added to provide functionality that is missing from
the underlying protocol - eg. message correlation, session orientation... or
to improved the efficiency of particular functional aspects - eg. a
MIME/DIME nestable binding could provide for the more efficient
serialisation of arbitrary attachments than say an internal base64
serialisation within the transmitted XML protocol envelope.

To provide a Binding Interface abstraction that supports an extensible (and
emergent) set of message exchange pattern we of a binding as supporting
operations with an explict lifecycle. Operations start, message get
exchanged and they end.

Drawing on the material in section 5 of the Abstract Model [6]:

Operation Livecycle Primitives (at a single binding interface)
------------------------------
Active initiation:		Passive initiation:
	Op.start-req			Op.start-ind
	Op.start-conf			Op.start-resp
		...					...
		...					...

Active termination:		Passive termination
		...					...
		...					...
	Op.end-req				Op.end-ind
	Op.end-conf				Op.end-resp

NB: This is intended to illustrate the passive and active initiation and
termination of an operation at a single node. Time progresses down the page.

Message transmission and reception can only occur (within this abstraction)
as part of a 'open' (not yet terminated) operation:

	Sender			Receiver

	Op.start-xxx		Op.start-xxx	;xxx=req or ind
	Op.start-yyy		Op.start-yyy	;yyy=conf or resp
		...			...
	Op.msg-send
				Op.msg-recv	;Message transfer
		...			...
	Op.end-xxx		Op.end-xxx
	Op.end-yyy		Op.end-yyy

NB. the only temporal constraint implied here between sender and receiver is
that Op.msg-recv occurs after the corresponding Op.msg-send.

Operation Lifecycle and Messaging primitives
--------------------------------------------
[This is just a 'sketch']

	Active initiation:
	------------------
	Op.start-req(PeerURI, MessagePattern, LocalBindingContext)
	Op.start-conf(Status, LocalBindingContext)

	Passive initiation
	------------------
	Op.start-ind(PeerURI, MessagePattern, LocalBindingContext)
	Op.start-resp(Status, LocalBindingContext)

	Active termination
	------------------
	Op.end-req(Reason, LocalBindingContext)
	Op.end-conf(Status, LocalBindingContext)

	Passive termination
	-------------------
	Op.end-ind(Reason, LocalBindingContext)
	Op.end-resp(Status, LocalBindingContext)

	Message Transmission
	--------------------
	Op.msg-send(Wrapper, Envelope, Attachments, 
			LocalCausality, Sequence, LocalBindingContext)

	Message Reception
	-----------------
	Op.msg-recv(Wrapper, Envelope, Attachments, 
			LocalCausality, Sequence, LocalBindingContext)

NB: May have been too liberal with inclusion of LocalBindingContext.
BindingContext carries through from AM section 3.

NB: On causality... as a starting point the thinking here is that discussed
in [7] and subsequent discussions. We may substituted the notion of a global
message reference rather than a local message reference. I would expect the
temporal scoping of a local message reference to be bounded by the lifetime
of the corresponding operation - ie. between Op.start-??? and Op.end-???

NB: It would be nice not to have to explicitly communicate a value for
MessagePattern. For HTTP on could imagine using HTTP PUT to do a pure
one-way message  from HTTP client to HTTP server. One-way and
request-response are both degenerate cases of request-multiresponse with
zero and one responses respectively. For conversational/session oriented
messages, LocalCausality threads the conversation at each local end.

NB: Bindings may augment the content of an envelope with additional headers
to enable non-native MEP's.


Example Message Exchange Patterns:
----------------------------------

One-Way:

	Sender:
		Op.start-req(PeerURI="destURI",
				 MessagePattern="one-way",
				 LocalBindingContext="sCtx1");

		Op.start-conf(Status="ok",
				  LocalBindingContext="sCtx2");

		Op.msg-send(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalBindingContext="sCtx3");

		Op.end-req(Reason="normal", 
			     LocalBindingContext="sCtx4");
		Op.end-conf(Status="ok"
				 LocalBindingContext="sCtx5");


	Receiver:
		Op.start-ind(PeerURI="fromURI",
				 MessagePattern="one-way",
				 LocalBindingContext="rCtx1");

		Op.start-resp(Status="ok",
				  LocalBindingContext="rCtx2");

		Op.msg.recv(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalbindingContext="rCtx3");

		Op.end-ind(Reason="normal",
			     LocalBindingContext="rCtx4");

		Op.end-resp(Status="ok",
				LocalBindingContext="rCtx5");

Request-Response:

	Sender:

		Op.start-req(PeerURI="destURI",
				 MessagePattern="request-response",
				 LocalBindingContext="sCtx1");

		Op.start-conf(Status="ok",
				  LocalBindingContext="sCtx2");

		Op.msg-send(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalBindingContext="sCtx3");

		Op.msg-recv(Envelope="envelope2",
				Attachments="attachments2",
				LocalCausality="&envelope1",
				Sequence="0",
				LocalBindingContext="sCtx4");

		Op.end-req(Reason="normal", 
			     LocalBindingContext="sCtx5");

		Op.end-conf(Status="ok"
				 LocalBindingContext="sCtx6");

	Receiver:
		Op.start-ind(PeerURI="fromURI",
				 MessagePattern="request-response",
				 LocalBindingContext="rCtx1");

		Op.start-resp(Status="ok",
				  LocalBindingContext="rCtx2");

		Op.msg-recv(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalbindingContext="rCtx3");

		Op.msg-send(Envelope="envelope2",
				Attachments="attachments2",
				LocalCausality="&envelope1",
				Sequence="0",
				LocalBindingContext="rCtx4");

		Op.end-ind(Reason="normal",
			     LocalBindingContext="rCtx5");

		Op.end-resp(Status="ok",
				LocalBindingContext="rCtx6");

Request-Multiresponse:
	Sender: (Note Passive termination)
		Op.start-req(PeerURI="destURI",
				 MessagePattern="request-response",
				 LocalBindingContext="sCtx1");

		Op.start-conf(Status="ok",
				  LocalBindingContext="sCtx2");

		Op.msg-send(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalBindingContext="sCtx3");

		Op.msg-recv(Envelope="envelope2",
				Attachments="attachments2",
				LocalCausality="&envelope1",
				Sequence="0",
				LocalBindingContext="sCtx4");

		Op.msg-recv(Envelope="envelope3",
				Attachments="attachments3",
				LocalCausality="&envelope1",
				Sequence="1",
				LocalBindingContext="sCtx5");

		Op.msg-recv(Envelope="envelope4",
				Attachments="attachments4",
				LocalCausality="&envelope1",
				Sequence="2",
				LocalBindingContext="sCtx6");

				...
				...

		Op.msg-recv(Envelope="envelopeN",
				Attachments="attachmentsN",
				LocalCausality="&envelope1",
				Sequence="N-1",
				LocalBindingContext="sCtx7");


		Op.end-ind(Reason="normal", 
			     LocalBindingContext="sCtx8");

		Op.end-resp(Status="ok"
				 LocalBindingContext="sCtx9");

	Receiver: (Note active termination)
		Op.start-ind(PeerURI="fromURI",
				 MessagePattern="request-response",
				 LocalBindingContext="rCtx1");

		Op.start-resp(Status="ok",
				  LocalBindingContext="rCtx2");

		Op.msg-recv(Envelope="envelope1",
				Attachments="attachments1",
				LocalCausality="null",
				Sequence="0",
				LocalbindingContext="rCtx3");

		Op.msg-send(Envelope="envelope2",
				Attachments="attachments2",
				LocalCausality="&envelope1",
				Sequence="0",
				LocalBindingContext="rCtx4");

		Op.msg-send(Envelope="envelope3",
				Attachments="attachments3",
				LocalCausality="&envelope1",
				Sequence="1",
				LocalBindingContext="rCtx5");

		Op.msg-send(Envelope="envelope4",
				Attachments="attachments4",
				LocalCausality="&envelope1",
				Sequence="2",
				LocalBindingContext="rCtx6");

				...
				...

		Op.msg-send(Envelope="envelopeN",
				Attachments="attachmentsN",
				LocalCausality="&envelope1",
				Sequence="N-2",
				LocalBindingContext="rCtx7");

		Op.end-req(Reason="normal",
			     LocalBindingContext="rCtx8");

		Op.end-conf(Status="ok",
				LocalBindingContext="rCtx9");


Example HTTP Binding and Request/Response MEP
---------------------------------------------
HTTP Request/Response via HTTP Post:

Sender:
	Op.start-req(PeerURI="destURI",
			 MessagePattern="request-response",
			 LocalBindingContext="sCtx1");

	Op.start-conf(Status="ok",
			  LocalBindingContext="sCtx2");

	Op.msg-send(Envelope="envelope1",
			Attachments="attachments1",
			LocalCausality="null",
			Sequence="0",
			LocalBindingContext="sCtx3");
							
			POST "destURI" HTTP/1.1
			Content-Type: text/xml
			Content-Length: NNNN
			SOAP-Action: <SoapActionURI from BindingCtx>
		
			<Env:Envelope ...>
				<Env:Headers>
					<!-- headers from "envelope1"-->
					...
				</Env:Headers>
				<Env:Body>
					<!-- bodies from "envelope1"-->
					...
				</Env:Body>

				<Env:Attachments>
					<!-- attachments from "attachment1"
-->
					<Env:Attachment id="Att1"
xsi:type="base64">
						...
					</Env:Attachment>
					<Env:Attachment id="Att2"
xsi:type="base64">
							...
					</Env:Attachment>
				</Env:Attachments>
			</Env:Envelope>

			HTTP/1.1 200 OK
			Content-Type: text/xml
			Content-Length: NNNN
		
			<Env:Envelope ...>
				<Env:Headers>
					<!-- headers from "envelope2"-->
					...
				</Env:Headers>
				<Env:Body>
					<!-- bodies from "envelope2"-->
					...
				</Env:Body>

				<Env:Attachments>
					<!-- attachments from "attachment2"
-->
					<Env:Attachment id="Att1"
xsi:type="base64">
						...
					</Env:Attachment>
					<Env:Attachment id="Att2"
xsi:type="base64">
						...
					</Env:Attachment>
				</Env:Attachments>
			</Env:Envelope>

	Op.msg-recv(Envelope="envelope2",
			Attachments="attachments2",
			LocalCausality="&envelope1",
			Sequence="0",
			LocalBindingContext="sCtx4");



	Op.end-req(Reason="normal", 
		     LocalBindingContext="sCtx5");

	Op.end-conf(Status="ok"
			 LocalBindingContext="sCtx6");

Receiver:
	Op.start-ind(PeerURI="fromURI",
			 MessagePattern="request-response",
			 LocalBindingContext="rCtx1");

	Op.start-resp(Status="ok",
			  LocalBindingContext="rCtx2");

				POST "destURI" HTTP/1.1
				Content-Type: text/xml
				Content-Length: NNNN
				SOAP-Action: <SoapActionURI from BindingCtx>
			
				<Env:Envelope ...>
					<Env:Headers>
						<!-- headers from
"envelope1"-->
						...
					</Env:Headers>
					<Env:Body>
						<!-- bodies from
"envelope1"-->
						...
					</Env:Body>

					<Env:Attachments>
						<!-- attachments from
"attachment1" -->
						<Env:Attachment id="Att1"
xsi:type="base64">
							...
						</Env:Attachment>
						<Env:Attachment id="Att2"
xsi:type="base64">
							...
						</Env:Attachment>
					</Env:Attachments>
				</Env:Envelope>

	Op.msg-recv(Envelope="envelope1",
			Attachments="attachments1",
			LocalCausality="null",
			Sequence="0",
			LocalbindingContext="rCtx3");


	Op.msg-send(Envelope="envelope2",
			Attachments="attachments2",
			LocalCausality="&envelope1",
			Sequence="0",
			LocalBindingContext="rCtx4");

				HTTP/1.1 200 OK
				Content-Type: text/xml
				Content-Length: NNNN
			
				<Env:Envelope ...>
					<Env:Headers>
						<!-- headers from
"envelope2"-->
						...
					</Env:Headers>
					<Env:Body>
						<!-- bodies from
"envelope2"-->
						...
					</Env:Body>

					<Env:Attachments>
						<!-- attachments from
"attachment2" -->
						<Env:Attachment id="Att1"
xsi:type="base64">
							...
						</Env:Attachment>
						<Env:Attachment id="Att2"
xsi:type="base64">
							...
						</Env:Attachment>
					</Env:Attachments>
				</Env:Envelope>

	Op.end-ind(Reason="normal",
		     LocalBindingContext="rCtx5");

	Op.end-resp(Status="ok",
			LocalBindingContext="rCtx6");

[1]
http://www.w3.org/2000/xp/Group/1/04/23/XMLProtocolAbstractModel.html#Fig5.1
[2] http://www.ietf.org/rfc/rfc2616.txt
[3] http://www.ietf.org/rfc/rfc2821.txt
[4] http://www.ietf.org/rfc/rfc0793.txt
[5] http://www.ietf.org/rfc/rfc3080.txt
[6]
http://www.w3.org/2000/xp/Group/1/04/23/XMLProtocolAbstractModel.html#Sec5
[7] http://lists.w3.org/Archives/Public/xml-dist-app/2001Mar/0216.html

Received on Tuesday, 3 July 2001 10:25:44 UTC