1 | var toIntIfInt = function (v) {
|
2 | return String(Number(v)) === v ? Number(v) : v;
|
3 | };
|
4 |
|
5 | var attachProperties = function (match, location, names, rawName) {
|
6 | if (rawName && !names) {
|
7 | location[rawName] = toIntIfInt(match[1]);
|
8 | }
|
9 | else {
|
10 | for (var i = 0; i < names.length; i += 1) {
|
11 | if (match[i+1] != null) {
|
12 | location[names[i]] = toIntIfInt(match[i+1]);
|
13 | }
|
14 | }
|
15 | }
|
16 | };
|
17 |
|
18 | var parseReg = function (obj, location, content) {
|
19 | var needsBlank = obj.name && obj.names;
|
20 | if (obj.push && !location[obj.push]) {
|
21 | location[obj.push] = [];
|
22 | }
|
23 | else if (needsBlank && !location[obj.name]) {
|
24 | location[obj.name] = {};
|
25 | }
|
26 | var keyLocation = obj.push ?
|
27 | {} :
|
28 | needsBlank ? location[obj.name] : location;
|
29 |
|
30 | attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name);
|
31 |
|
32 | if (obj.push) {
|
33 | location[obj.push].push(keyLocation);
|
34 | }
|
35 | };
|
36 |
|
37 | var grammar = require('./grammar');
|
38 | var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/);
|
39 |
|
40 | exports.parse = function (sdp) {
|
41 | var session = {}
|
42 | , media = []
|
43 | , location = session;
|
44 |
|
45 |
|
46 | sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) {
|
47 | var type = l[0];
|
48 | var content = l.slice(2);
|
49 | if (type === 'm') {
|
50 | media.push({rtp: [], fmtp: []});
|
51 | location = media[media.length-1];
|
52 | }
|
53 |
|
54 | for (var j = 0; j < (grammar[type] || []).length; j += 1) {
|
55 | var obj = grammar[type][j];
|
56 | if (obj.reg.test(content)) {
|
57 | return parseReg(obj, location, content);
|
58 | }
|
59 | }
|
60 | });
|
61 |
|
62 | session.media = media;
|
63 | return session;
|
64 | };
|
65 |
|
66 | var paramReducer = function (acc, expr) {
|
67 | var s = expr.split(/=(.+)/, 2);
|
68 | if (s.length === 2) {
|
69 | acc[s[0]] = toIntIfInt(s[1]);
|
70 | } else if (s.length === 1 && expr.length > 1) {
|
71 | acc[s[0]] = undefined;
|
72 | }
|
73 | return acc;
|
74 | };
|
75 |
|
76 | exports.parseParams = function (str) {
|
77 | return str.split(/;\s?/).reduce(paramReducer, {});
|
78 | };
|
79 |
|
80 |
|
81 | exports.parseFmtpConfig = exports.parseParams;
|
82 |
|
83 | exports.parsePayloads = function (str) {
|
84 | return str.toString().split(' ').map(Number);
|
85 | };
|
86 |
|
87 | exports.parseRemoteCandidates = function (str) {
|
88 | var candidates = [];
|
89 | var parts = str.split(' ').map(toIntIfInt);
|
90 | for (var i = 0; i < parts.length; i += 3) {
|
91 | candidates.push({
|
92 | component: parts[i],
|
93 | ip: parts[i + 1],
|
94 | port: parts[i + 2]
|
95 | });
|
96 | }
|
97 | return candidates;
|
98 | };
|
99 |
|
100 | exports.parseImageAttributes = function (str) {
|
101 | return str.split(' ').map(function (item) {
|
102 | return item.substring(1, item.length-1).split(',').reduce(paramReducer, {});
|
103 | });
|
104 | };
|
105 |
|
106 | exports.parseSimulcastStreamList = function (str) {
|
107 | return str.split(';').map(function (stream) {
|
108 | return stream.split(',').map(function (format) {
|
109 | var scid, paused = false;
|
110 |
|
111 | if (format[0] !== '~') {
|
112 | scid = toIntIfInt(format);
|
113 | } else {
|
114 | scid = toIntIfInt(format.substring(1, format.length));
|
115 | paused = true;
|
116 | }
|
117 |
|
118 | return {
|
119 | scid: scid,
|
120 | paused: paused
|
121 | };
|
122 | });
|
123 | });
|
124 | };
|