summaryrefslogtreecommitdiffstats
path: root/comm/chat/protocols/matrix/lib/sdp-transform/parser.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comm/chat/protocols/matrix/lib/sdp-transform/parser.js124
1 files changed, 124 insertions, 0 deletions
diff --git a/comm/chat/protocols/matrix/lib/sdp-transform/parser.js b/comm/chat/protocols/matrix/lib/sdp-transform/parser.js
new file mode 100644
index 0000000000..ac863971a7
--- /dev/null
+++ b/comm/chat/protocols/matrix/lib/sdp-transform/parser.js
@@ -0,0 +1,124 @@
+var toIntIfInt = function (v) {
+ return String(Number(v)) === v ? Number(v) : v;
+};
+
+var attachProperties = function (match, location, names, rawName) {
+ if (rawName && !names) {
+ location[rawName] = toIntIfInt(match[1]);
+ }
+ else {
+ for (var i = 0; i < names.length; i += 1) {
+ if (match[i+1] != null) {
+ location[names[i]] = toIntIfInt(match[i+1]);
+ }
+ }
+ }
+};
+
+var parseReg = function (obj, location, content) {
+ var needsBlank = obj.name && obj.names;
+ if (obj.push && !location[obj.push]) {
+ location[obj.push] = [];
+ }
+ else if (needsBlank && !location[obj.name]) {
+ location[obj.name] = {};
+ }
+ var keyLocation = obj.push ?
+ {} : // blank object that will be pushed
+ needsBlank ? location[obj.name] : location; // otherwise, named location or root
+
+ attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
+
+ if (obj.push) {
+ location[obj.push].push(keyLocation);
+ }
+};
+
+var grammar = require('./grammar');
+var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
+
+exports.parse = function (sdp) {
+ var session = {}
+ , media = []
+ , location = session; // points at where properties go under (one of the above)
+
+ // parse lines we understand
+ sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
+ var type = l[0];
+ var content = l.slice(2);
+ if (type === 'm') {
+ media.push({rtp: [], fmtp: []});
+ location = media[media.length-1]; // point at latest media line
+ }
+
+ for (var j = 0; j < (grammar[type] || []).length; j += 1) {
+ var obj = grammar[type][j];
+ if (obj.reg.test(content)) {
+ return parseReg(obj, location, content);
+ }
+ }
+ });
+
+ session.media = media; // link it up
+ return session;
+};
+
+var paramReducer = function (acc, expr) {
+ var s = expr.split(/=(.+)/, 2);
+ if (s.length === 2) {
+ acc[s[0]] = toIntIfInt(s[1]);
+ } else if (s.length === 1 && expr.length > 1) {
+ acc[s[0]] = undefined;
+ }
+ return acc;
+};
+
+exports.parseParams = function (str) {
+ return str.split(/;\s?/).reduce(paramReducer, {});
+};
+
+// For backward compatibility - alias will be removed in 3.0.0
+exports.parseFmtpConfig = exports.parseParams;
+
+exports.parsePayloads = function (str) {
+ return str.toString().split(' ').map(Number);
+};
+
+exports.parseRemoteCandidates = function (str) {
+ var candidates = [];
+ var parts = str.split(' ').map(toIntIfInt);
+ for (var i = 0; i < parts.length; i += 3) {
+ candidates.push({
+ component: parts[i],
+ ip: parts[i + 1],
+ port: parts[i + 2]
+ });
+ }
+ return candidates;
+};
+
+exports.parseImageAttributes = function (str) {
+ return str.split(' ').map(function (item) {
+ return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});
+ });
+};
+
+exports.parseSimulcastStreamList = function (str) {
+ return str.split(';').map(function (stream) {
+ return stream.split(',').map(function (format) {
+ var scid, paused = false;
+
+ if (format[0] !== '~') {
+ scid = toIntIfInt(format);
+ } else {
+ scid = toIntIfInt(format.substring(1, format.length));
+ paused = true;
+ }
+
+ return {
+ scid: scid,
+ paused: paused
+ };
+ });
+ });
+};