[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