jingle-stanza
Version:
A jingle.js utility for creating xml stanzas from objects
300 lines (276 loc) • 8.75 kB
JavaScript
'use strict';
var NS = 'urn:xmpp:jingle:apps:rtp:1';
var DCNS = 'urn:xmpp:jingle:transports:webrtc-datachannel:0';
var FBNS = 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0';
var HDRNS = 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0';
var INFONS = 'urn:xmpp:jingle:apps:rtp:info:1';
var SSMANS = 'urn:xmpp:jingle:apps:rtp:ssma:0';
var GROUPNS = 'urn:xmpp:jingle:apps:grouping:0';
module.exports = function (stanza) {
var types = stanza.utils;
var Feedback = {
get: function () {
var existing = types.find(this.xml, FBNS, 'rtcp-fb');
var result = [];
existing.forEach(function (xml) {
result.push({
type: types.getAttribute(xml, 'type'),
subtype: types.getAttribute(xml, 'subtype')
});
});
existing = types.find(this.xml, FBNS, 'rtcp-fb-trr-int');
existing.forEach(function (xml) {
result.push({
type: types.getAttribute(xml, 'type'),
value: types.getAttribute(xml, 'value')
});
});
return result;
},
set: function (values) {
var self = this;
var existing = types.find(this.xml, FBNS, 'rtcp-fb');
existing.forEach(function (item) {
self.xml.removeChild(item);
});
existing = types.find(this.xml, FBNS, 'rtcp-fb-trr-int');
existing.forEach(function (item) {
self.xml.removeChild(item);
});
values.forEach(function (value) {
var fb;
if (value.type === 'trr-int') {
fb = types.createElement(FBNS, 'rtcp-fb-trr-int', NS);
types.setAttribute(fb, 'type', value.type);
types.setAttribute(fb, 'value', value.value);
} else {
fb = types.createElement(FBNS, 'rtcp-fb', NS);
types.setAttribute(fb, 'type', value.type);
types.setAttribute(fb, 'subtype', value.subtype);
}
self.xml.appendChild(fb);
});
}
};
var Bandwidth = stanza.define({
name: 'bandwidth',
namespace: NS,
element: 'bandwidth',
fields: {
type: types.attribute('type'),
bandwidth: types.text()
}
});
var RTP = stanza.define({
name: '_rtp',
namespace: NS,
element: 'description',
tags: ['jingle-application'],
fields: {
applicationType: {value: 'rtp'},
media: types.attribute('media'),
ssrc: types.attribute('ssrc'),
mux: types.boolSub(NS, 'rtcp-mux'),
rsize: types.boolSub(NS, 'rtcp-rsize'),
encryption: {
get: function () {
var enc = types.find(this.xml, NS, 'encryption');
if (!enc.length) {
return [];
}
enc = enc[0];
var self = this;
var data = types.find(enc, NS, 'crypto');
var results = [];
data.forEach(function (xml) {
results.push(new Crypto({}, xml, self).toJSON());
});
return results;
},
set: function (values) {
var enc = types.find(this.xml, NS, 'encryption');
if (enc.length) {
this.xml.removeChild(enc);
}
if (!values.length) {
return;
}
types.setBoolSubAttribute(this.xml, NS, 'encryption', 'required', true);
enc = types.find(this.xml, NS, 'encryption')[0];
var self = this;
values.forEach(function (value) {
var content = new Crypto(value, null, self);
enc.appendChild(content.xml);
});
}
},
feedback: Feedback,
headerExtensions: {
get: function () {
var existing = types.find(this.xml, HDRNS, 'rtp-hdrext');
var result = [];
existing.forEach(function (xml) {
result.push({
id: types.getAttribute(xml, 'id'),
uri: types.getAttribute(xml, 'uri'),
senders: types.getAttribute(xml, 'senders')
});
});
return result;
},
set: function (values) {
var self = this;
var existing = types.find(this.xml, HDRNS, 'rtp-hdrext');
existing.forEach(function (item) {
self.xml.removeChild(item);
});
values.forEach(function (value) {
var hdr = types.createElement(HDRNS, 'rtp-hdrext', NS);
types.setAttribute(hdr, 'id', value.id);
types.setAttribute(hdr, 'uri', value.uri);
types.setAttribute(hdr, 'senders', value.senders);
self.xml.appendChild(hdr);
});
}
}
}
});
var DataChannel = stanza.define({
name: '_datachannel',
namespace: DCNS,
element: 'description',
tags: ['jingle-application'],
fields: {
applicationType: {value: 'datachannel'}
}
});
var PayloadType = stanza.define({
name: '_payloadType',
namespace: NS,
element: 'payload-type',
fields: {
channels: types.attribute('channels'),
clockrate: types.attribute('clockrate'),
id: types.attribute('id'),
maxptime: types.attribute('maxptime'),
name: types.attribute('name'),
ptime: types.attribute('ptime'),
feedback: Feedback,
parameters: {
get: function () {
var result = [];
var params = types.find(this.xml, NS, 'parameter');
params.forEach(function (param) {
result.push({
key: types.getAttribute(param, 'name'),
value: types.getAttribute(param, 'value')
});
});
return result;
},
set: function (values) {
var self = this;
values.forEach(function (value) {
var param = types.createElement(NS, 'parameter');
types.setAttribute(param, 'name', value.key);
types.setAttribute(param, 'value', value.value);
self.xml.appendChild(param);
});
}
}
}
});
var Crypto = stanza.define({
name: 'crypto',
namespace: NS,
element: 'crypto',
fields: {
cipherSuite: types.attribute('crypto-suite'),
keyParams: types.attribute('key-params'),
sessionParams: types.attribute('session-params'),
tag: types.attribute('tag')
}
});
var ContentGroup = stanza.define({
name: '_group',
namespace: GROUPNS,
element: 'group',
fields: {
semantics: types.attribute('semantics'),
contents: types.multiSubAttribute(GROUPNS, 'content', 'name')
}
});
var SourceGroup = stanza.define({
name: '_sourceGroup',
namespace: SSMANS,
element: 'ssrc-group',
fields: {
semantics: types.attribute('semantics'),
sources: types.multiSubAttribute(SSMANS, 'source', 'ssrc')
}
});
var Source = stanza.define({
name: '_source',
namespace: SSMANS,
element: 'source',
fields: {
ssrc: types.attribute('ssrc'),
parameters: {
get: function () {
var result = [];
var params = types.find(this.xml, SSMANS, 'parameter');
params.forEach(function (param) {
result.push({
key: types.getAttribute(param, 'name'),
value: types.getAttribute(param, 'value')
});
});
return result;
},
set: function (values) {
var self = this;
values.forEach(function (value) {
var param = types.createElement(SSMANS, 'parameter');
types.setAttribute(param, 'name', value.key);
types.setAttribute(param, 'value', value.value);
self.xml.appendChild(param);
});
}
}
}
});
var Mute = stanza.define({
name: 'mute',
namespace: INFONS,
element: 'mute',
fields: {
creator: types.attribute('creator'),
name: types.attribute('name')
}
});
var Unmute = stanza.define({
name: 'unmute',
namespace: INFONS,
element: 'unmute',
fields: {
creator: types.attribute('creator'),
name: types.attribute('name')
}
});
stanza.extend(RTP, Bandwidth);
stanza.extend(RTP, PayloadType, 'payloads');
stanza.extend(RTP, Source, 'sources');
stanza.extend(RTP, SourceGroup, 'sourceGroups');
stanza.withDefinition('content', 'urn:xmpp:jingle:1', function (Content) {
stanza.extend(Content, RTP);
stanza.extend(Content, DataChannel);
});
stanza.withDefinition('jingle', 'urn:xmpp:jingle:1', function (Jingle) {
stanza.extend(Jingle, Mute);
stanza.extend(Jingle, Unmute);
stanza.extend(Jingle, ContentGroup, 'groups');
stanza.add(Jingle, 'ringing', types.boolSub(INFONS, 'ringing'));
stanza.add(Jingle, 'hold', types.boolSub(INFONS, 'hold'));
stanza.add(Jingle, 'active', types.boolSub(INFONS, 'active'));
});
};