XMPP stream multiplexing
----
S: <stream:features>
S: <multiplex xmlns='ns:multiplex'/>
S: </stream:features>
C: <enable xmlns='ns:multiplex'/>
S: <enabled xmlns='ns:multiplex'/>
From this point forward, all data exchanged with the server must use this
framing format:
[UINT channel] [UINT value length] [value bytes]
UINT is an unsigned integer of variable length, encoded as follows:
The number spans a series of bytes. Each byte has Bit 8 set to one,
except for the last byte in the series. This means that every byte
can at most represent 7 bits of the overall value. A value that is
7 bits or less can be represented in a single byte. A value that is
8 bits will require two bytes. The bits are ordered starting with
the most significant bit. Since the value is rounded to 7-bit boundaries,
it may be necessary to pad the most significant bits with 0 for the
value to align properly. E.g: 12 = 00001100, 1025 = 10000100 00000001.
For example:
00 0B 3C 70 72 65 73 65 6E 63 65 2F 3E
Would mean:
Channel: 0
Value: <presence/>
Channel 0 is the XML stream, and operates the same as always. Channel 1 and
higher may be used for some other purpose. Additionally, since the value
sizes are known by the recipient, channel usages can make use of this
knowledge.
The framing protocol sits under the XML stream, however it is always above
all other layer negotiations. For example, if TLS or compression is
negotiated on channel 0, then the entire multiplex stream is encrypted or
compressed, not simply the channel 0 XML stream. These layer negotiation
protocols have an indicator for where the new layer should begin (for
example, with TLS, this is after the final '>' of '<proceed/>'). When
using multiplex, the new layer begins after the channel 0 frame containing
this indicator. Since the multiplex framing protocol has no footer, this
point is mostly moot (the last byte in the frame containing '<proceed/>'
would be '>', so it works out the same whether or not multiplex framing
is used).
IBB using stream multiplexing
----
Either peer can send IBB data over alternate channels by using <ibbbind>.
Typical IBB handshake:
C0: <iq type='set'
C0: from='romeo@montague.net/orchard'
C0: to='juliet@capulet.com/balcony'
C0: id='inband_1'>
C0: <open sid='mySID'
C0: block-size='4096'
C0: xmlns='http://jabber.org/protocol/ibb'/>
C0: </iq>
S0: <iq type='result'
S0: from='juliet@capulet.com/balcony'
S0: to='romeo@montague.net/orchard'
S0: id='inband_1'/>
Client sets channel 1 to be used for this IBB stream:
C0: <ibbbind xmlns='ns:multiplex'
C0: from='romeo@montague.net/orchard'
C0: to='juliet@capulet.com/balcony'
C0: sid='mySID'
C0: channel='1'/>
Client sends some IBB packets:
C1: Hello world
C1: Data sent on this channel is not Base64 encoded
Server replies also using a channel:
S0: <ibbbind xmlns='ns:multiplex'
S0: from='juliet@capulet.com/balcony'
S0: to='romeo@montague.net/orchard'
S0: sid='mySID'
S0: channel='1'/>
S1: You're right, and neither is this data!
A binding is only in one direction, and only for a single c2s/s2s stream.
The binding ends when the ibb stream ends.