[jdev] Stream Initiation: extension

Mats Bengtsson matben at privat.utfors.se
Thu Sep 27 02:18:14 CDT 2007


Dear all,

Introduction:
-------------

While I was trying to implement the SVG graphics model in my whiteboard
I was getting problems with elements that have an external reference.
In short, SVG images typically have a xlink:href attribute with a HTTP
link which wont work in a XMPP environment with p2p interaction due to
NATs, firewalls etc. A typical SVG image element looks like:

<image x='32.0' y='32.0' 
       xlink:href='http://192.168.0.3:8077/blender.png' 
       id='158229644' width='128' height='128'/>

Putting an ibb element as a child is not an option.

Using Stream Initiation (XEP-0095) wont work either since this is using an
iq-set/si method which can't be embedded in an image element. Using iq-set/si
directly with some extra info telling the target this is a SVG image wont
be compatible with existing implementations. 

The problem with SI (Stream Initiation) in this context is that it effectively
is a PUT operation while we require a GET method (like HTTP) for it to
be embeddable. You have to interpret this yourself since it is badly expressed.

Instead I switched the order SI works by embedding the si element inside a
message, as a child to the image element, and let the target send an iq-get/si,
note the *get*, to the initiator (the entity that sent the image element).
In this way an arbitrary number of embedded si elements (images) can be 
contained in a message. Compare with HTTP/HTML: a client obtains a HTML 
document containing a number of HTTP references which it GETs.

The targets iq-get/si element corresponds almost exactly to the targets
response to an iq-set/si element, see note below. Since the embedded si
element is identical to the si in an iq-set query, the target will select
which stream it wants, and include this in its response, which is now a
iq-get query instead of the iq-result in the existing SI standard.

Two differences exist compared to XEP. The first is that since we don't get
an iq-set id attribute we must use the id attribute of the si element (SID) as
a reference in the stream negotiating. Thus, the iq-get/si element MUST contain
a SID which is used by the initiator as the reference to its stream offer.

Cited from the XEP:
"This attribute MUST be present on type='set', and MUST be a valid string. 
 This SHOULD NOT be sent back on type='result', since the <iq/> "id" attribute 
 provides the only context needed."

The second difference is that since the target sends an iq-get/si it needs
a response. Either an iq-result if the SID was indeed made by the initiator,
or an iq-error if not found. The iq-result element should be empty.

Comparison:

         XEP            this                task

      iq-set/si      si subelement     offer stream initiation
     iq-result/si      iq-get/si       select stream (or deny)
         -             iq-result           dummy

The rest using the actual streams goes on unchanged.


Use Case:
---------

This is seen from the initiator, the one who sends a message containing a
SVG image, and offers stream initiation:

SEND:
<message to='mari at mus.se/work' type='chat'>
  <thread>ee2944c6</thread>
  <x xmlns='http://jabber.org/protocol/svgwb'>
    <image x='32.0' y='32.0' 
	   xlink:href='http://192.168.0.3:8077/blender.png' 
	   id='158229644' width='128' height='128'>
      <si xmlns='http://jabber.org/protocol/si' 
	  id='3c803c10-6983032b' mime-type='image/png' 
	  profile='http://jabber.org/protocol/si/profile/file-transfer'>
	<file xmlns='http://jabber.org/protocol/si/profile/file-transfer' 
	      name='blender.png' size='12582'/>
	<feature xmlns='http://jabber.org/protocol/feature-neg'>
	  <x xmlns='jabber:x:data' type='form'>
	    <field var='stream-method' type='list-single'>
	      <option><value>http://jabber.org/protocol/bytestreams</value></option>
	      <option><value>http://jabber.org/protocol/ibb</value></option>
	    </field>
	  </x>
	</feature>
      </si>
    </image>
  </x>
</message>

You see that the si element is completely identical to the XEP standard.
Then the target responds and we get:

RECV: 
<iq from='mari at mus.se/work' 
    to='mats at home.se/coci' xml:lang='sv' 
    type='get' id='1011'>
  <si xmlns='http://jabber.org/protocol/si' 
      id='3c803c10-6983032b'>
    <feature xmlns='http://jabber.org/protocol/feature-neg'>
      <x xmlns='jabber:x:data' type='submit'>
	<field var='stream-method'>
	  <value>http://jabber.org/protocol/bytestreams</value>
	</field>
      </x>
    </feature>
    <file name='blender.png' size='12582' 
	  xmlns='http://jabber.org/protocol/si/profile/file-transfer'/>
  </si>
</iq>

Note the iq-get and note that it contains a SID which MUST be there.
Since we are the initiator of this SID we just respond with:

SEND: 
<iq type='result' id='1011' to='mari at mus.se/work'/>

And from here things go on as usual.


Discussion:
-----------

It would be very practical if we could find some kind of URI which could be
used as a global reference to the file since this fits better with the GET
method described here, but I see all the problems finding such a representation.

The PUT method from the XEP is a single instance, and when finished it is gone
forever. In the GET scenario we would like to see a persistant file reference
which allows files to be obtained several times.

This method wont work for groupchats due to what I just said, but this is a 
general problem with SI in groupchats. Instead, we must direct stream
offers to each participant.


Any thoughts?

The Coccinella cvs (http://coccinella.im) contains a working implementation
of SVG whiteboards including image transports as described here.
See also: http://coccinella.im/node/103

/Mats



More information about the JDev mailing list