diff --git a/.gitignore b/.gitignore index dd87e2d..16d2e37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules build +.vscode diff --git a/.travis.yml b/.travis.yml index 21f9b08..fb20e2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ sudo: false language: node_js node_js: - - '0.10' + - 10 diff --git a/lib/tojson.js b/lib/tojson.js index 91a807c..33a5444 100644 --- a/lib/tojson.js +++ b/lib/tojson.js @@ -24,6 +24,10 @@ exports.toSessionJSON = function (sdp, opts) { } var session = media.shift() + '\r\n'; var sessionLines = parsers.lines(session); + var type; + if (sessionLines[0].indexOf('type:') >= 0) { + type = sessionLines[0].split('type:')[1].split(',')[0].trim(); + } var parsed = {}; var contents = []; @@ -35,6 +39,7 @@ exports.toSessionJSON = function (sdp, opts) { })); } parsed.contents = contents; + parsed.type = type; var groupLines = parsers.findLines('a=group:', sessionLines); if (groupLines.length) { @@ -60,6 +65,7 @@ exports.toMediaJSON = function (media, session, opts) { applicationType: 'rtp', media: mline.media, payloads: [], + port: mline.port, encryption: [], feedback: [], headerExtensions: [] @@ -73,8 +79,17 @@ exports.toMediaJSON = function (media, session, opts) { if (mline.media == 'application') { // FIXME: the description is most likely to be independent // of the SDP and should be processed by other parts of the library + + var sctpLine = parsers.findLine('a=sctp-port', lines); + var sctpPort = sctpLine && sctpLine.split('sctp-port:')[1]; + var maxMessageSizeLine = parsers.findLine('a=max-message-size', lines); + var maxMessageSize = maxMessageSizeLine && maxMessageSizeLine.split('max-message-size:')[1]; + content.application = { - applicationType: 'datachannel' + applicationType: 'datachannel', + port: mline.port, + sctpPort: sctpPort, + maxMessageSize: maxMessageSize }; content.transport.sctp = []; } @@ -194,6 +209,10 @@ exports.toMediaJSON = function (media, session, opts) { trans.fingerprints.push(fp); }); + if (parsers.findLine('a=ice-options:trickle', lines)) { + trans.trickleIce = true; + } + var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines); var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines); if (ufragLine && pwdLine) { diff --git a/lib/tosdp.js b/lib/tosdp.js index 7621a17..594e469 100644 --- a/lib/tosdp.js +++ b/lib/tosdp.js @@ -7,8 +7,10 @@ exports.toSessionSDP = function (session, opts) { var sid = opts.sid || session.sid || Date.now(); var time = opts.time || Date.now(); + var type = (session.type && 'type: ' + session.type + ', ') || ''; + var sdp = [ - 'v=0', + type + 'sdp: v=0', 'o=- ' + sid + ' ' + time + ' IN IP4 0.0.0.0', 's=-', 't=0 0' @@ -54,8 +56,9 @@ exports.toMediaSDP = function (content, opts) { var mline = []; if (desc.applicationType == 'datachannel') { mline.push('application'); - mline.push('1'); - mline.push('DTLS/SCTP'); + mline.push(desc.port); + mline.push('UDP/DTLS/SCTP'); + mline.push('webrtc-datachannel'); if (transport.sctp) { transport.sctp.forEach(function (map) { mline.push(map.number); @@ -63,7 +66,7 @@ exports.toMediaSDP = function (content, opts) { } } else { mline.push(desc.media); - mline.push('1'); + mline.push(desc.port); if (fingerprints.length > 0) { mline.push('UDP/TLS/RTP/SAVPF'); } else if (desc.encryption && desc.encryption.length > 0) { @@ -76,7 +79,6 @@ exports.toMediaSDP = function (content, opts) { }); } - sdp.push('m=' + mline.join(' ')); sdp.push('c=IN IP4 0.0.0.0'); @@ -84,7 +86,15 @@ exports.toMediaSDP = function (content, opts) { sdp.push('b=' + desc.bandwidth.type + ':' + desc.bandwidth.bandwidth); } if (desc.applicationType == 'rtp') { - sdp.push('a=rtcp:1 IN IP4 0.0.0.0'); + sdp.push('a=rtcp:' + desc.port + ' IN IP4 0.0.0.0'); + } + + if (desc.maxMessageSize) { + sdp.push('a=max-message-size:' + desc.maxMessageSize); + } + + if (desc.sctpPort) { + sdp.push('a=sctp-port:' + desc.sctpPort); } if (transport) { @@ -94,6 +104,9 @@ exports.toMediaSDP = function (content, opts) { if (transport.pwd) { sdp.push('a=ice-pwd:' + transport.pwd); } + if (transport.trickleIce) { + sdp.push('a=ice-options:trickle'); + } var pushedSetup = false; fingerprints.forEach(function (fingerprint) { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2212847 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1185 @@ +{ + "name": "sdp-jingle-json", + "version": "3.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "Base64": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.1.4.tgz", + "integrity": "sha1-6fbGvvVn/WNepBYqsU3TKedKpt4=", + "dev": true + }, + "JSONStream": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.6.4.tgz", + "integrity": "sha1-SyyAY/j1Enh7I3X37p22kgj6Lcs=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": "~2.2.7" + }, + "dependencies": { + "through": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", + "integrity": "sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0=", + "dev": true + } + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "argparse": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz", + "integrity": "sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw=", + "dev": true, + "requires": { + "underscore": "~1.7.0", + "underscore.string": "~2.4.0" + }, + "dependencies": { + "underscore.string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz", + "integrity": "sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs=", + "dev": true + } + } + }, + "astw": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-0.0.0.tgz", + "integrity": "sha1-RJCGaj7xFqr5GtumPKfd9wttWb0=", + "dev": true, + "requires": { + "esprima": "1.0.2" + } + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "dev": true + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "dev": true, + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + }, + "dependencies": { + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", + "dev": true + } + } + }, + "browser-builtins": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/browser-builtins/-/browser-builtins-2.0.5.tgz", + "integrity": "sha1-ETuPZx9G4McJ3tg4dQy2BMQQIjs=", + "dev": true, + "requires": { + "buffer-browserify": "0.2.x", + "console-browserify": "~1.0.1", + "constants-browserify": "0.0.x", + "crypto-browserify": "1.0.x", + "http-browserify": "0.1.x", + "os-browserify": "0.1.x", + "punycode": "1.2.x", + "vm-browserify": "0.0.x", + "zlib-browserify": "0.0.x" + } + }, + "browser-pack": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-1.1.0.tgz", + "integrity": "sha1-go2fbR93wMVqnLVzdfcI3yWkaXc=", + "dev": true, + "requires": { + "JSONStream": "~0.6.4", + "combine-source-map": "~0.3.0", + "through": "~2.3.4" + } + }, + "browser-resolve": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.2.4.tgz", + "integrity": "sha1-Wa54IKgpVezTL1+3xGisIcRyOAY=", + "dev": true, + "requires": { + "resolve": "0.6.3" + } + }, + "browserify": { + "version": "2.36.1", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-2.36.1.tgz", + "integrity": "sha1-SZg58fj7+gWB+/T60Xpphxme+mk=", + "dev": true, + "requires": { + "JSONStream": "~0.6.4", + "browser-builtins": "2.0.5", + "browser-pack": "~1.1.0", + "browser-resolve": "~1.2.0", + "concat-stream": "~1.0.0", + "deep-equal": "~0.1.0", + "deps-sort": "~0.1.1", + "duplexer": "~0.1.1", + "inherits": "~1.0.0", + "insert-module-globals": "~1.3.0", + "module-deps": "~1.1.0", + "optimist": "~0.5.1", + "parents": "~0.0.1", + "shell-quote": "~0.0.1", + "stream-combiner": "~0.0.2", + "syntax-error": "~0.0.0", + "through": "~2.3.4", + "umd": "~1.3.0" + } + }, + "browserify-shim": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/browserify-shim/-/browserify-shim-2.0.10.tgz", + "integrity": "sha1-dKDtW5t4SlooeQZROoltMfVKhLg=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "buffer-browserify": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/buffer-browserify/-/buffer-browserify-0.2.5.tgz", + "integrity": "sha1-Kcc51qTiR7U5q8CtoHNhIAIWOiE=", + "dev": true, + "requires": { + "base64-js": "0.0.8" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cli": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/cli/-/cli-0.4.5.tgz", + "integrity": "sha1-ePlIXNFhtWbppsctcXDEJw6B22E=", + "dev": true, + "requires": { + "glob": ">= 3.1.4" + } + }, + "coffee-script": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.3.3.tgz", + "integrity": "sha1-FQ1rTLUiiUNp7+1qIQHCC8f0pPQ=", + "dev": true + }, + "coffeelint": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-0.5.7.tgz", + "integrity": "sha1-PRJc3emV1kHL2ECwrFNsXN9vaNs=", + "dev": true, + "requires": { + "coffee-script": ">=1.6.0", + "glob": ">=3.1.9", + "optimist": ">=0.2.8" + }, + "dependencies": { + "coffee-script": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.2.tgz", + "integrity": "sha1-/ZyINpweQeMwegoWDXE/IlE8k7M=", + "dev": true + }, + "glob": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.14.tgz", + "integrity": "sha1-+XpzHEHaZpXcg5RLuyF36aKbNj0=", + "dev": true, + "requires": { + "graceful-fs": "~1.1.2", + "inherits": "1", + "minimatch": "0.2" + }, + "dependencies": { + "graceful-fs": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz", + "integrity": "sha1-BweNtfY3f2Mh/Oqu30l94STclGU=", + "dev": true + }, + "inherits": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz", + "integrity": "sha1-OOGXUoW/H3upyE2hArsSdxMirEg=", + "dev": true + }, + "minimatch": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.9.tgz", + "integrity": "sha1-uAr5R+aoOoxo8m5UwNYSW6yfiH8=", + "dev": true, + "requires": { + "lru-cache": "~2.0.0", + "sigmund": "~1.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.0.4.tgz", + "integrity": "sha1-uLYa4JhIOF7Gdodg45wSPn45Voo=", + "dev": true + }, + "sigmund": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", + "integrity": "sha1-ZqKzp0mui1+4nv1PzAHclPvgIpY=", + "dev": true + } + } + } + } + }, + "optimist": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.5.tgz", + "integrity": "sha1-A2VLUkFwMDEtEJ85sVmCW2AwkwQ=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "vows": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/vows/-/vows-0.7.0.tgz", + "integrity": "sha1-3QBl8RC6DAptY+hEhRwyCBdtWGc=", + "requires": { + "diff": "~1.0.3", + "eyes": ">=0.1.6" + }, + "dependencies": { + "diff": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.4.tgz", + "integrity": "sha1-+P4oT7rB1lHUGxHTzqkT/ZOM2RU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + } + } + } + } + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=", + "dev": true + }, + "combine-source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.3.0.tgz", + "integrity": "sha1-2edPWT2c1DgHMSy12EbUUe+qnrc=", + "dev": true, + "requires": { + "convert-source-map": "~0.3.0", + "inline-source-map": "~0.3.0", + "source-map": "~0.1.31" + } + }, + "commondir": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.2.tgz", + "integrity": "sha1-xJyIgMb+loRLs1Jd0ucxQFDDie4=", + "dev": true + }, + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "dev": true, + "requires": { + "bops": "0.0.6" + } + }, + "console-browserify": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.0.3.tgz", + "integrity": "sha1-04mNLDqTEC82QZf4h0tPkrUoao4=", + "dev": true + }, + "constants-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-0.0.1.tgz", + "integrity": "sha1-kld9tSe6bEzwpFaNhLwDH0QeIfI=", + "dev": true + }, + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "crypto-browserify": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-1.0.9.tgz", + "integrity": "sha1-zFRJaF37hesRyYKKzHy4erW7/MA=", + "dev": true + }, + "dateformat": { + "version": "1.0.2-1.2.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz", + "integrity": "sha1-sCIMAt6YYXQztyhRz0fePfLNvuk=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-equal": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", + "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", + "dev": true + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "deps-sort": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-0.1.2.tgz", + "integrity": "sha1-2qL7YUoXyWN9gB4vVTOa43DzYRo=", + "dev": true, + "requires": { + "JSONStream": "~0.6.4", + "minimist": "~0.0.1", + "through": "~2.3.4" + } + }, + "detective": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detective/-/detective-2.1.2.tgz", + "integrity": "sha1-0irZ8YyC77P1X+4uJEiD2mu7jjc=", + "dev": true, + "requires": { + "escodegen": "0.0.15", + "esprima": "1.0.2" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "escodegen": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.15.tgz", + "integrity": "sha1-/9qcsmtws098wZ8diHVlOa+1Q70=", + "dev": true, + "requires": { + "esprima": ">= 1.0.0", + "source-map": ">= 0.1.2" + } + }, + "esprima": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.2.tgz", + "integrity": "sha1-gDm/nOrE2dLBX2IyZPspK1UCzq8=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "findup-sync": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.1.3.tgz", + "integrity": "sha1-fz56l7gjksZTvwZYm9hRkOk8NoM=", + "dev": true, + "requires": { + "glob": "~3.2.9", + "lodash": "~2.4.1" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "grunt": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-0.4.2.tgz", + "integrity": "sha1-iVtPKKYQK//UHTZaZei+LWopPZM=", + "dev": true, + "requires": { + "async": "~0.1.22", + "coffee-script": "~1.3.3", + "colors": "~0.6.2", + "dateformat": "1.0.2-1.2.3", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.1.2", + "getobject": "~0.1.0", + "glob": "~3.1.21", + "hooker": "~0.2.3", + "iconv-lite": "~0.2.11", + "js-yaml": "~2.0.5", + "lodash": "~0.9.2", + "minimatch": "~0.2.12", + "nopt": "~1.0.10", + "rimraf": "~2.0.3", + "underscore.string": "~2.2.1", + "which": "~1.0.5" + }, + "dependencies": { + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=", + "dev": true + } + } + }, + "grunt-browserify": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/grunt-browserify/-/grunt-browserify-1.2.11.tgz", + "integrity": "sha1-Q4Dvo65O/+v4Dj5n6q6x6F7o9Qg=", + "dev": true, + "requires": { + "browserify-shim": "~2.0.8", + "through": "~2.3.4" + } + }, + "grunt-contrib-jshint": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.7.2.tgz", + "integrity": "sha1-KYWd3PQuf2xUxD/nXaPEvZA4So4=", + "dev": true, + "requires": { + "jshint": "~2.3.0" + } + }, + "grunt-contrib-uglify": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-0.2.7.tgz", + "integrity": "sha1-5r2lHgxAoUWfbOrUI8Ze/XJaG/c=", + "dev": true, + "requires": { + "grunt-lib-contrib": "~0.6.1", + "uglify-js": "~2.4.0" + } + }, + "grunt-lib-contrib": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/grunt-lib-contrib/-/grunt-lib-contrib-0.6.1.tgz", + "integrity": "sha1-P1att9oG6BR5XuJBWw6+X7iQPrs=", + "dev": true, + "requires": { + "zlib-browserify": "0.0.1" + }, + "dependencies": { + "zlib-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.1.tgz", + "integrity": "sha1-T6akXQDbwV8xikr6HZr8Aljhdsw=", + "dev": true + } + } + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "http-browserify": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-0.1.14.tgz", + "integrity": "sha1-nIs/lAAiBFR8fL5Saa/i6mL3HH8=", + "dev": true, + "requires": { + "Base64": "~0.1.2", + "concat-stream": "~1.0.0" + } + }, + "iconv-lite": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.2.11.tgz", + "integrity": "sha1-HOYKOleGSiktEyH/RgnKS7llrcg=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "inline-source-map": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.3.1.tgz", + "integrity": "sha1-pSi1FOaJ/OkNswiehw2S9Sestes=", + "dev": true, + "requires": { + "source-map": "~0.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.3.0.tgz", + "integrity": "sha1-hYb7mloAXltQHiHNGLbyG0V60fk=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "insert-module-globals": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-1.3.1.tgz", + "integrity": "sha1-S5R91JcSsk+ynstQZ2iyomosVz8=", + "dev": true, + "requires": { + "JSONStream": "~0.4.3", + "commondir": "~0.0.1", + "duplexer": "~0.0.3", + "lexical-scope": "~0.0.5", + "process": "~0.5.1", + "through": "~2.2.0" + }, + "dependencies": { + "JSONStream": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.4.4.tgz", + "integrity": "sha1-zCzxGShsRb4VBCPLwSjUgOm1SuI=", + "dev": true, + "requires": { + "jsonparse": "0.0.5" + } + }, + "duplexer": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.0.4.tgz", + "integrity": "sha1-r8t/H4uNdPggcmFx1dZKyeSo/yA=", + "dev": true + }, + "through": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/through/-/through-2.2.7.tgz", + "integrity": "sha1-bo4hIAGR1OtqmfbwEN9Gqhxusr0=", + "dev": true + } + } + }, + "js-yaml": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-2.0.5.tgz", + "integrity": "sha1-olrmUJmZ6X3yeMZxnaEb0Gh3Q6g=", + "dev": true, + "requires": { + "argparse": "~ 0.1.11", + "esprima": "~ 1.0.2" + } + }, + "jshint": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.3.0.tgz", + "integrity": "sha1-GVBEVaLCDEbuGDNh64fzocC33Ec=", + "dev": true, + "requires": { + "cli": "0.4.x", + "console-browserify": "0.1.x", + "minimatch": "0.x.x", + "shelljs": "0.1.x", + "underscore": "1.4.x" + }, + "dependencies": { + "console-browserify": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", + "integrity": "sha1-0SijwLuINQ61YmxufHGm8P1ImDw=", + "dev": true + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + } + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "lexical-scope": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-0.0.15.tgz", + "integrity": "sha1-yllZl6rth7FVywQfSNwEOPSKBNw=", + "dev": true, + "requires": { + "astw": "~0.0.0" + } + }, + "lodash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-0.9.2.tgz", + "integrity": "sha1-jzSZxSRdNG1oLlsNO0B2fgnxqSw=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "module-deps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-1.1.0.tgz", + "integrity": "sha1-NUXi16V/QHLU2kQrtgTQSxRAlLo=", + "dev": true, + "requires": { + "JSONStream": "~0.6.4", + "browser-resolve": "~1.2.0", + "concat-stream": "~1.0.0", + "detective": "~2.1.2", + "minimist": "~0.0.1", + "resolve": "~0.6.0", + "through": "~2.3.4" + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "optimist": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.5.2.tgz", + "integrity": "sha1-hcjBRUszFeSniUfoV7HfAzRQv7w=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "parents": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/parents/-/parents-0.0.3.tgz", + "integrity": "sha1-+iEvAk2fpjGNu2tM5nbIvkk7nEM=", + "dev": true, + "requires": { + "path-platform": "^0.0.1" + } + }, + "path-platform": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.0.1.tgz", + "integrity": "sha1-tVhdfDxGPYmqAGDYZhHPGv1hfio=", + "dev": true + }, + "precommit-hook": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/precommit-hook/-/precommit-hook-0.3.8.tgz", + "integrity": "sha1-Mcv2eyBxcfuX1UWdeFIh9MuoRNI=", + "dev": true, + "requires": { + "coffeelint": "~0.5.4", + "jshint": "~2.1.4" + }, + "dependencies": { + "console-browserify": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-0.1.6.tgz", + "integrity": "sha1-0SijwLuINQ61YmxufHGm8P1ImDw=", + "dev": true + }, + "jshint": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.1.11.tgz", + "integrity": "sha1-61EI/vm6Xd67gwmD9XLSQuSeP5Y=", + "dev": true, + "requires": { + "cli": "0.4.x", + "console-browserify": "0.1.x", + "minimatch": "0.x.x", + "shelljs": "0.1.x", + "underscore": "1.4.x" + } + }, + "underscore": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", + "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", + "dev": true + } + } + }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", + "dev": true + }, + "punycode": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=", + "dev": true + }, + "resolve": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", + "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", + "dev": true + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rfile": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rfile/-/rfile-1.0.0.tgz", + "integrity": "sha1-WXCM+Qyh50xUw8/Fw2/bmBBDUmE=", + "dev": true, + "requires": { + "callsite": "~1.0.0", + "resolve": "~0.3.0" + }, + "dependencies": { + "resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.3.1.tgz", + "integrity": "sha1-NMY0R8ZkxwWY0cmxJvxDsqJDEKQ=", + "dev": true + } + } + }, + "rimraf": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.0.3.tgz", + "integrity": "sha1-9QopZecUTpr9mYmC8V33BnMPVqk=", + "dev": true, + "requires": { + "graceful-fs": "~1.1" + }, + "dependencies": { + "graceful-fs": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz", + "integrity": "sha1-BweNtfY3f2Mh/Oqu30l94STclGU=", + "dev": true, + "optional": true + } + } + }, + "ruglify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ruglify/-/ruglify-1.0.0.tgz", + "integrity": "sha1-3Ikw4qlUSidDAcyZcldMDQmGtnU=", + "dev": true, + "requires": { + "rfile": "~1.0", + "uglify-js": "~2.2" + }, + "dependencies": { + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "requires": { + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + } + } + }, + "shell-quote": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-0.0.1.tgz", + "integrity": "sha1-GkEZbzwDM8SCMjWT1ohuzxU92YY=", + "dev": true + }, + "shelljs": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.1.4.tgz", + "integrity": "sha1-37vnjVbDwBaNL7eeEOzR28sH7A4=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "split": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/split/-/split-0.2.10.tgz", + "integrity": "sha1-Zwl8YB1pfOE2j0GPBs0gHPBSGlc=", + "dev": true, + "requires": { + "through": "2" + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, + "syntax-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-0.0.1.tgz", + "integrity": "sha1-AZ0HU0jNjFt58GA8c+U4kafFI10=", + "dev": true, + "requires": { + "esprima": "~0.9.9" + }, + "dependencies": { + "esprima": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-0.9.9.tgz", + "integrity": "sha1-G5CSXJddYy1ygpOcO7nDpCPDBJA=", + "dev": true + } + } + }, + "tape": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.0.tgz", + "integrity": "sha1-Df7scJIn+8yRcKvn8EaWKycUMds=", + "dev": true, + "requires": { + "deep-equal": "~0.1.0", + "defined": "~0.0.0", + "inherits": "~2.0.1", + "jsonify": "~0.0.0", + "resumer": "~0.0.0", + "split": "~0.2.10", + "stream-combiner": "~0.0.2", + "through": "~2.3.4" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", + "dev": true + }, + "uglify-js": { + "version": "2.4.24", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.4.24.tgz", + "integrity": "sha1-+tV1XB4Vd2WLsG/5q25UjJW+vW4=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "0.1.34", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.5.4" + }, + "dependencies": { + "source-map": { + "version": "0.1.34", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.34.tgz", + "integrity": "sha1-p8/omux7FoLDsZjQrPtH19CQVms=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/umd/-/umd-1.3.1.tgz", + "integrity": "sha1-/OVXwtv3MfvCB4Mv819qWFcYJYk=", + "dev": true, + "requires": { + "rfile": "~1.0.0", + "ruglify": "~1.0.0", + "through": "~2.3.4", + "uglify-js": "~2.4.0" + } + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "underscore.string": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.2.1.tgz", + "integrity": "sha1-18D6KvXVoaZ/QlPa7pgTLnM/Dxk=", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "which": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/which/-/which-1.0.9.tgz", + "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "yargs": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.5.4.tgz", + "integrity": "sha1-2K/49mXpTDS9JZvevRv68N3TU2E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "decamelize": "^1.0.0", + "window-size": "0.1.0", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "zlib-browserify": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.3.tgz", + "integrity": "sha1-JAzNv9AgP6hCsTDe77FBQSLIzFA=", + "dev": true, + "requires": { + "tape": "~0.2.2" + }, + "dependencies": { + "deep-equal": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", + "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", + "dev": true + }, + "tape": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/tape/-/tape-0.2.2.tgz", + "integrity": "sha1-ZMz6S37PSgBgAH5hcW1CR4FnFjc=", + "dev": true, + "requires": { + "deep-equal": "~0.0.0", + "defined": "~0.0.0", + "jsonify": "~0.0.0" + } + } + } + } + } +} diff --git a/test/data/json.js b/test/data/json.js index 7e2ffea..315ac1f 100644 --- a/test/data/json.js +++ b/test/data/json.js @@ -2,7 +2,7 @@ module.exports = { "contents": [ { "creator": "initiator", - "name": "audio", + "name": "0", "application": { "applicationType": "rtp", "media": "audio", @@ -12,11 +12,22 @@ module.exports = { "name": "opus", "clockrate": "48000", "channels": "2", - "feedback": [], "parameters": [ { "key": "minptime", "value": "10" + }, + { + "key": "useinbandfec", + "value": "1" + } + ], + "feedback": [ + { + "id": "111", + "type": "transport-cc", + "subtype": "", + "parameters": [] } ] }, @@ -25,113 +36,150 @@ module.exports = { "name": "ISAC", "clockrate": "16000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { "id": "104", "name": "ISAC", "clockrate": "32000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] + }, + { + "id": "9", + "name": "G722", + "clockrate": "8000", + "channels": "1", + "parameters": [], + "feedback": [] }, { "id": "0", "name": "PCMU", "clockrate": "8000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { "id": "8", "name": "PCMA", "clockrate": "8000", "channels": "1", - "feedback": [], - "parameters": [] - }, - { - "id": "107", - "name": "CN", - "clockrate": "48000", - "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { "id": "106", "name": "CN", "clockrate": "32000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { "id": "105", "name": "CN", "clockrate": "16000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { "id": "13", "name": "CN", "clockrate": "8000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] + }, + { + "id": "110", + "name": "telephone-event", + "clockrate": "48000", + "channels": "1", + "parameters": [], + "feedback": [] + }, + { + "id": "112", + "name": "telephone-event", + "clockrate": "32000", + "channels": "1", + "parameters": [], + "feedback": [] + }, + { + "id": "113", + "name": "telephone-event", + "clockrate": "16000", + "channels": "1", + "parameters": [], + "feedback": [] }, { "id": "126", "name": "telephone-event", "clockrate": "8000", "channels": "1", - "feedback": [], - "parameters": [] - } - ], - "encryption": [ - { - "tag": "1", - "cipherSuite": "AES_CM_128_HMAC_SHA1_80", - "keyParams": "inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", - "sessionParams": "" + "parameters": [], + "feedback": [] } ], + "port": "9", + "encryption": [], "feedback": [], "headerExtensions": [ { "id": "1", - "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level", - "senders": "both" + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level" + }, + { + "id": "2", + "senders": "both", + "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" + }, + { + "id": "3", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:mid" + }, + { + "id": "4", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id" + }, + { + "id": "5", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id" } ], - "ssrc": "445948959", + "ssrc": "1357361180", "mux": true, - "rsize": true, "sourceGroups": [], "sources": [ { - "ssrc": "445948959", + "ssrc": "1357361180", "parameters": [ { "key": "cname", - "value": "RbR04HtIjW+Sa+yz" + "value": "l4UVyLdoOcWXiwUs" }, { "key": "msid", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta 40c1b8ba-4986-42ad-9b60-0d2c15355a70" }, { "key": "mslabel", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta" }, { "key": "label", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0" + "value": "40c1b8ba-4986-42ad-9b60-0d2c15355a70" } ] } @@ -139,44 +187,160 @@ module.exports = { }, "transport": { "transportType": "iceUdp", - "candidates": [ - { - "foundation": "1529647030", - "component": "1", - "protocol": "udp", - "priority": "2113937151", - "ip": "192.12.211.22", - "port": "63522", - "type": "host", - "generation": "0", - "network": "1", - "id": "0" - } - ], + "candidates": [], "fingerprints": [ { "hash": "sha-256", - "value": "39:52:60:61:9D:6B:97:2A:43:DE:E0:BD:80:4B:2D:EE:A3:00:72:FE:FF:11:8E:43:85:06:4A:14:80:FE:9F:DD" + "value": "AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "setup": "actpass" } ], - "ufrag": "TESg/uYDt8nNomZd", - "pwd": "abQXlDvFdLKIVdRDdg1t5Tbn" + "trickleIce": true, + "ufrag": "tMuf", + "pwd": "86QW7lRCWJVsrKy/4NTMDNKr" }, "senders": "both" }, { "creator": "initiator", - "name": "video", + "name": "1", "application": { "applicationType": "rtp", "media": "video", "payloads": [ { - "id": "100", + "id": "96", "name": "VP8", "clockrate": "90000", "channels": "1", + "parameters": [], "feedback": [ + { + "id": "96", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "96", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "96", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "96", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "96", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "97", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "96" + } + ], + "feedback": [] + }, + { + "id": "98", + "name": "VP9", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "profile-id", + "value": "0" + } + ], + "feedback": [ + { + "id": "98", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "98", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "98", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "98", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "98", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "99", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "98" + } + ], + "feedback": [] + }, + { + "id": "100", + "name": "VP9", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "profile-id", + "value": "2" + } + ], + "feedback": [ + { + "id": "100", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "100", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, { "id": "100", "type": "ccm", @@ -191,94 +355,562 @@ module.exports = { }, { "id": "100", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "101", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "100" + } + ], + "feedback": [] + }, + { + "id": "102", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "1" + }, + { + "key": "profile-level-id", + "value": "42001f" + } + ], + "feedback": [ + { + "id": "102", "type": "goog-remb", "subtype": "", "parameters": [] + }, + { + "id": "102", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "102", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "102", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "102", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "122", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "102" } ], - "parameters": [] + "feedback": [] }, { - "id": "116", + "id": "127", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "0" + }, + { + "key": "profile-level-id", + "value": "42001f" + } + ], + "feedback": [ + { + "id": "127", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "127", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "127", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "127", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "127", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "121", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "127" + } + ], + "feedback": [] + }, + { + "id": "125", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "1" + }, + { + "key": "profile-level-id", + "value": "42e01f" + } + ], + "feedback": [ + { + "id": "125", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "125", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "125", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "125", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "125", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "107", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "125" + } + ], + "feedback": [] + }, + { + "id": "108", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "0" + }, + { + "key": "profile-level-id", + "value": "42e01f" + } + ], + "feedback": [ + { + "id": "108", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "108", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "108", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "108", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "108", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "109", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "108" + } + ], + "feedback": [] + }, + { + "id": "124", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "1" + }, + { + "key": "profile-level-id", + "value": "4d0032" + } + ], + "feedback": [ + { + "id": "124", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "124", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "124", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "124", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "124", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "120", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "124" + } + ], + "feedback": [] + }, + { + "id": "123", + "name": "H264", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "level-asymmetry-allowed", + "value": "1" + }, + { + "key": "packetization-mode", + "value": "1" + }, + { + "key": "profile-level-id", + "value": "640032" + } + ], + "feedback": [ + { + "id": "123", + "type": "goog-remb", + "subtype": "", + "parameters": [] + }, + { + "id": "123", + "type": "transport-cc", + "subtype": "", + "parameters": [] + }, + { + "id": "123", + "type": "ccm", + "subtype": "fir", + "parameters": [] + }, + { + "id": "123", + "type": "nack", + "subtype": "", + "parameters": [] + }, + { + "id": "123", + "type": "nack", + "subtype": "pli", + "parameters": [] + } + ] + }, + { + "id": "119", + "name": "rtx", + "clockrate": "90000", + "channels": "1", + "parameters": [ + { + "key": "apt", + "value": "123" + } + ], + "feedback": [] + }, + { + "id": "114", "name": "red", "clockrate": "90000", "channels": "1", - "feedback": [], - "parameters": [] + "parameters": [], + "feedback": [] }, { - "id": "117", - "name": "ulpfec", + "id": "115", + "name": "rtx", "clockrate": "90000", "channels": "1", - "feedback": [], - "parameters": [] - } - ], - "encryption": [ + "parameters": [ + { + "key": "apt", + "value": "114" + } + ], + "feedback": [] + }, { - "tag": "1", - "cipherSuite": "AES_CM_128_HMAC_SHA1_80", - "keyParams": "inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", - "sessionParams": "" + "id": "116", + "name": "ulpfec", + "clockrate": "90000", + "channels": "1", + "parameters": [], + "feedback": [] } ], + "port": "9", + "encryption": [], "feedback": [], "headerExtensions": [ + { + "id": "14", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:toffset" + }, + { + "id": "13", + "senders": "both", + "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time" + }, + { + "id": "12", + "senders": "both", + "uri": "urn:3gpp:video-orientation" + }, { "id": "2", - "uri": "urn:ietf:params:rtp-hdrext:toffset", - "senders": "both" + "senders": "both", + "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" + }, + { + "id": "11", + "senders": "both", + "uri": "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay" + }, + { + "id": "6", + "senders": "both", + "uri": "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type" + }, + { + "id": "7", + "senders": "both", + "uri": "http://www.webrtc.org/experiments/rtp-hdrext/video-timing" + }, + { + "id": "8", + "senders": "both", + "uri": "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07" + }, + { + "id": "9", + "senders": "both", + "uri": "http://www.webrtc.org/experiments/rtp-hdrext/color-space" + }, + { + "id": "3", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:mid" + }, + { + "id": "4", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id" + }, + { + "id": "5", + "senders": "both", + "uri": "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id" } ], - "ssrc": "797563643", + "ssrc": "230994796", "mux": true, + "rsize": true, "sourceGroups": [ { "semantics": "FID", - "sources": ["797563643", "193463643"] + "sources": [ + "230994796", + "1243325027" + ] } ], "sources": [ { - "ssrc": "797563643", + "ssrc": "230994796", "parameters": [ { "key": "cname", - "value": "RbR04HtIjW+Sa+yz" + "value": "l4UVyLdoOcWXiwUs" }, { "key": "msid", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta cdb21b44-1ec2-456f-a5bd-5837a89af8f6" }, { "key": "mslabel", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta" }, { "key": "label", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" + "value": "cdb21b44-1ec2-456f-a5bd-5837a89af8f6" } ] }, { - "ssrc": "193463643", + "ssrc": "1243325027", "parameters": [ { "key": "cname", - "value": "RbR04HtIjW+Sa+yz" + "value": "l4UVyLdoOcWXiwUs" }, { "key": "msid", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta cdb21b44-1ec2-456f-a5bd-5837a89af8f6" }, { "key": "mslabel", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" + "value": "H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta" }, { "key": "label", - "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" + "value": "cdb21b44-1ec2-456f-a5bd-5837a89af8f6" } ] } @@ -286,38 +918,54 @@ module.exports = { }, "transport": { "transportType": "iceUdp", - "candidates": [ - { - "foundation": "1529647030", - "component": "1", - "protocol": "udp", - "priority": "2113937151", - "ip": "192.12.211.22", - "port": "63522", - "type": "host", - "generation": "0", - "network": "1", - "id": "1" - } - ], + "candidates": [], "fingerprints": [ { "hash": "sha-256", - "value": "39:52:60:61:9D:6B:97:2A:43:DE:E0:BD:80:4B:2D:EE:A3:00:72:FE:FF:11:8E:43:85:06:4A:14:80:FE:9F:DD" + "value": "AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "setup": "actpass" } ], - "ufrag": "TESg/uYDt8nNomZd", - "pwd": "abQXlDvFdLKIVdRDdg1t5Tbn" + "trickleIce": true, + "ufrag": "tMuf", + "pwd": "86QW7lRCWJVsrKy/4NTMDNKr" }, "senders": "both" + }, + { + "creator": "initiator", + "name": "2", + "application": { + "applicationType": "datachannel", + "port": "9", + "sctpPort": "5000", + "maxMessageSize": "262144" + }, + "transport": { + "transportType": "iceUdp", + "candidates": [], + "fingerprints": [ + { + "hash": "sha-256", + "value": "AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "setup": "actpass" + } + ], + "sctp": [], + "trickleIce": true, + "ufrag": "tMuf", + "pwd": "86QW7lRCWJVsrKy/4NTMDNKr" + } } ], + "type": "offer", "groups": [ { "semantics": "BUNDLE", "contents": [ - "audio", - "video" + "0", + "1", + "2" ] } ] diff --git a/test/data/no-source-json.js b/test/data/no-source-json.js index 88c3232..182f80e 100644 --- a/test/data/no-source-json.js +++ b/test/data/no-source-json.js @@ -1,4 +1,5 @@ module.exports = { + "type": undefined, "contents": [ { "creator": "initiator", @@ -29,6 +30,7 @@ module.exports = { "feedback": [] } ], + "port": "1", "encryption": [], "feedback": [], "headerExtensions": [], diff --git a/test/data/no-source-sdp.js b/test/data/no-source-sdp.js index 1bb3534..914131d 100644 --- a/test/data/no-source-sdp.js +++ b/test/data/no-source-sdp.js @@ -1,5 +1,5 @@ module.exports = [ - "v=0", + "sdp: v=0", "o=- 1382398245712 1385147470924 IN IP4 0.0.0.0", "s=-", "t=0 0", diff --git a/test/data/sdp.js b/test/data/sdp.js index 3130869..820e7e6 100644 --- a/test/data/sdp.js +++ b/test/data/sdp.js @@ -1,66 +1,173 @@ module.exports = [ - "v=0", - "o=- 1382398245712 1385147470924 IN IP4 0.0.0.0", + "type: offer, sdp: v=0", + "o=- 6569601038001417104 2 IN IP4 127.0.0.1", "s=-", "t=0 0", - "a=msid-semantic: WMS *", - "a=group:BUNDLE audio video", - "m=audio 1 UDP/TLS/RTP/SAVPF 111 103 104 0 8 107 106 105 13 126", + "a=group:BUNDLE 0 1 2", + "a=msid-semantic: WMS H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta", + "m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126", "c=IN IP4 0.0.0.0", - "a=rtcp:1 IN IP4 0.0.0.0", - "a=ice-ufrag:TESg/uYDt8nNomZd", - "a=ice-pwd:abQXlDvFdLKIVdRDdg1t5Tbn", - "a=fingerprint:sha-256 39:52:60:61:9D:6B:97:2A:43:DE:E0:BD:80:4B:2D:EE:A3:00:72:FE:FF:11:8E:43:85:06:4A:14:80:FE:9F:DD", + "a=rtcp:9 IN IP4 0.0.0.0", + "a=ice-ufrag:tMuf", + "a=ice-pwd:86QW7lRCWJVsrKy/4NTMDNKr", + "a=ice-options:trickle", + "a=fingerprint:sha-256 AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "a=setup:actpass", + "a=mid:0", + "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level", + "a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01", + "a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid", + "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", + "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id", "a=sendrecv", - "a=mid:audio", - "a=msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0", + "a=msid:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta 40c1b8ba-4986-42ad-9b60-0d2c15355a70", "a=rtcp-mux", - "a=rtcp-rsize", - "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", "a=rtpmap:111 opus/48000/2", - "a=fmtp:111 minptime=10", + "a=rtcp-fb:111 transport-cc", + "a=fmtp:111 minptime=10;useinbandfec=1", "a=rtpmap:103 ISAC/16000", "a=rtpmap:104 ISAC/32000", + "a=rtpmap:9 G722/8000", "a=rtpmap:0 PCMU/8000", "a=rtpmap:8 PCMA/8000", - "a=rtpmap:107 CN/48000", "a=rtpmap:106 CN/32000", "a=rtpmap:105 CN/16000", "a=rtpmap:13 CN/8000", + "a=rtpmap:110 telephone-event/48000", + "a=rtpmap:112 telephone-event/32000", + "a=rtpmap:113 telephone-event/16000", "a=rtpmap:126 telephone-event/8000", - "a=extmap:1/sendrecv urn:ietf:params:rtp-hdrext:ssrc-audio-level", - "a=ssrc:445948959 cname:RbR04HtIjW+Sa+yz", - "a=ssrc:445948959 msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0", - "a=ssrc:445948959 mslabel:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo", - "a=ssrc:445948959 label:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0", - "a=candidate:1529647030 1 UDP 2113937151 192.12.211.22 63522 typ host generation 0", - "m=video 1 UDP/TLS/RTP/SAVPF 100 116 117", + "a=ssrc:1357361180 cname:l4UVyLdoOcWXiwUs", + "a=ssrc:1357361180 msid:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta 40c1b8ba-4986-42ad-9b60-0d2c15355a70", + "a=ssrc:1357361180 mslabel:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta", + "a=ssrc:1357361180 label:40c1b8ba-4986-42ad-9b60-0d2c15355a70", + "m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 122 127 121 125 107 108 109 124 120 123 119 114 115 116", "c=IN IP4 0.0.0.0", - "a=rtcp:1 IN IP4 0.0.0.0", - "a=ice-ufrag:TESg/uYDt8nNomZd", - "a=ice-pwd:abQXlDvFdLKIVdRDdg1t5Tbn", - "a=fingerprint:sha-256 39:52:60:61:9D:6B:97:2A:43:DE:E0:BD:80:4B:2D:EE:A3:00:72:FE:FF:11:8E:43:85:06:4A:14:80:FE:9F:DD", + "a=rtcp:9 IN IP4 0.0.0.0", + "a=ice-ufrag:tMuf", + "a=ice-pwd:86QW7lRCWJVsrKy/4NTMDNKr", + "a=ice-options:trickle", + "a=fingerprint:sha-256 AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "a=setup:actpass", + "a=mid:1", + "a=extmap:14 urn:ietf:params:rtp-hdrext:toffset", + "a=extmap:13 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", + "a=extmap:12 urn:3gpp:video-orientation", + "a=extmap:2 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01", + "a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay", + "a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type", + "a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing", + "a=extmap:8 http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07", + "a=extmap:9 http://www.webrtc.org/experiments/rtp-hdrext/color-space", + "a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid", + "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", + "a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id", "a=sendrecv", - "a=mid:video", - "a=msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", + "a=msid:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta cdb21b44-1ec2-456f-a5bd-5837a89af8f6", "a=rtcp-mux", - "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", - "a=rtpmap:100 VP8/90000", + "a=rtcp-rsize", + "a=rtpmap:96 VP8/90000", + "a=rtcp-fb:96 goog-remb", + "a=rtcp-fb:96 transport-cc", + "a=rtcp-fb:96 ccm fir", + "a=rtcp-fb:96 nack", + "a=rtcp-fb:96 nack pli", + "a=rtpmap:97 rtx/90000", + "a=fmtp:97 apt=96", + "a=rtpmap:98 VP9/90000", + "a=rtcp-fb:98 goog-remb", + "a=rtcp-fb:98 transport-cc", + "a=rtcp-fb:98 ccm fir", + "a=rtcp-fb:98 nack", + "a=rtcp-fb:98 nack pli", + "a=fmtp:98 profile-id=0", + "a=rtpmap:99 rtx/90000", + "a=fmtp:99 apt=98", + "a=rtpmap:100 VP9/90000", + "a=rtcp-fb:100 goog-remb", + "a=rtcp-fb:100 transport-cc", "a=rtcp-fb:100 ccm fir", "a=rtcp-fb:100 nack", - "a=rtcp-fb:100 goog-remb", - "a=rtpmap:116 red/90000", - "a=rtpmap:117 ulpfec/90000", - "a=extmap:2/sendrecv urn:ietf:params:rtp-hdrext:toffset", - "a=ssrc-group:FID 797563643 193463643", - "a=ssrc:797563643 cname:RbR04HtIjW+Sa+yz", - "a=ssrc:797563643 msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", - "a=ssrc:797563643 mslabel:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo", - "a=ssrc:797563643 label:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", - "a=ssrc:193463643 cname:RbR04HtIjW+Sa+yz", - "a=ssrc:193463643 msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", - "a=ssrc:193463643 mslabel:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo", - "a=ssrc:193463643 label:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", - "a=candidate:1529647030 1 UDP 2113937151 192.12.211.22 63522 typ host generation 0", + "a=rtcp-fb:100 nack pli", + "a=fmtp:100 profile-id=2", + "a=rtpmap:101 rtx/90000", + "a=fmtp:101 apt=100", + "a=rtpmap:102 H264/90000", + "a=rtcp-fb:102 goog-remb", + "a=rtcp-fb:102 transport-cc", + "a=rtcp-fb:102 ccm fir", + "a=rtcp-fb:102 nack", + "a=rtcp-fb:102 nack pli", + "a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", + "a=rtpmap:122 rtx/90000", + "a=fmtp:122 apt=102", + "a=rtpmap:127 H264/90000", + "a=rtcp-fb:127 goog-remb", + "a=rtcp-fb:127 transport-cc", + "a=rtcp-fb:127 ccm fir", + "a=rtcp-fb:127 nack", + "a=rtcp-fb:127 nack pli", + "a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", + "a=rtpmap:121 rtx/90000", + "a=fmtp:121 apt=127", + "a=rtpmap:125 H264/90000", + "a=rtcp-fb:125 goog-remb", + "a=rtcp-fb:125 transport-cc", + "a=rtcp-fb:125 ccm fir", + "a=rtcp-fb:125 nack", + "a=rtcp-fb:125 nack pli", + "a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", + "a=rtpmap:107 rtx/90000", + "a=fmtp:107 apt=125", + "a=rtpmap:108 H264/90000", + "a=rtcp-fb:108 goog-remb", + "a=rtcp-fb:108 transport-cc", + "a=rtcp-fb:108 ccm fir", + "a=rtcp-fb:108 nack", + "a=rtcp-fb:108 nack pli", + "a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f", + "a=rtpmap:109 rtx/90000", + "a=fmtp:109 apt=108", + "a=rtpmap:124 H264/90000", + "a=rtcp-fb:124 goog-remb", + "a=rtcp-fb:124 transport-cc", + "a=rtcp-fb:124 ccm fir", + "a=rtcp-fb:124 nack", + "a=rtcp-fb:124 nack pli", + "a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032", + "a=rtpmap:120 rtx/90000", + "a=fmtp:120 apt=124", + "a=rtpmap:123 H264/90000", + "a=rtcp-fb:123 goog-remb", + "a=rtcp-fb:123 transport-cc", + "a=rtcp-fb:123 ccm fir", + "a=rtcp-fb:123 nack", + "a=rtcp-fb:123 nack pli", + "a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032", + "a=rtpmap:119 rtx/90000", + "a=fmtp:119 apt=123", + "a=rtpmap:114 red/90000", + "a=rtpmap:115 rtx/90000", + "a=fmtp:115 apt=114", + "a=rtpmap:116 ulpfec/90000", + "a=ssrc-group:FID 230994796 1243325027", + "a=ssrc:230994796 cname:l4UVyLdoOcWXiwUs", + "a=ssrc:230994796 msid:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta cdb21b44-1ec2-456f-a5bd-5837a89af8f6", + "a=ssrc:230994796 mslabel:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta", + "a=ssrc:230994796 label:cdb21b44-1ec2-456f-a5bd-5837a89af8f6", + "a=ssrc:1243325027 cname:l4UVyLdoOcWXiwUs", + "a=ssrc:1243325027 msid:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta cdb21b44-1ec2-456f-a5bd-5837a89af8f6", + "a=ssrc:1243325027 mslabel:H48tXd3FYkzxkS2CnnyKjnUWYqUYthkLy4ta", + "a=ssrc:1243325027 label:cdb21b44-1ec2-456f-a5bd-5837a89af8f6", + "m=application 9 UDP/DTLS/SCTP webrtc-datachannel", + "c=IN IP4 0.0.0.0", + "a=ice-ufrag:tMuf", + "a=ice-pwd:86QW7lRCWJVsrKy/4NTMDNKr", + "a=ice-options:trickle", + "a=fingerprint:sha-256 AE:F3:14:B8:BD:7D:43:F7:B9:DD:0B:73:6A:0C:2B:FB:81:26:7C:7D:34:A6:F3:4B:01:AF:9A:6E:D0:58:74:AE", + "a=setup:actpass", + "a=mid:2", + "a=sctp-port:5000", + "a=max-message-size:262144", "" // So we end with a \r\n ].join('\r\n'); diff --git a/test/test.js b/test/test.js index 0984076..9c70721 100644 --- a/test/test.js +++ b/test/test.js @@ -4,6 +4,7 @@ var fs = require('fs'); var test = require('tape'); var SJJ = require('../index'); var tojson = require('../lib/tojson'); +var validateSdp = require('./validate-sdp'); var jsonData = require('./data/json'); var sdpData = require('./data/sdp'); @@ -35,7 +36,7 @@ test('to sdp', function (t) { time: time }); - t.deepEqual(sdp, sdpData); + validateSdp(t, sdp, sdpData); t.end(); }); @@ -66,8 +67,6 @@ test('no source to sdp', function (t) { }); test('multiple pases', function (t) { - t.plan(2); - tojson._setIdCounter(0); var json1 = SJJ.toSessionJSON(sdpData, { creator: 'initiator', @@ -95,6 +94,6 @@ test('multiple pases', function (t) { }); t.deepEqual(json2, jsonData); - t.deepEqual(sdp2, sdpData); + validateSdp(t, sdp2, sdpData); t.end(); }); diff --git a/test/validate-sdp.js b/test/validate-sdp.js new file mode 100644 index 0000000..3210cfd --- /dev/null +++ b/test/validate-sdp.js @@ -0,0 +1,99 @@ +var matchOverrides = [ + { output: /o=- \d+ \d+ IN IP4 0.0.0.0/, original: /o=- \d+ \d+ IN IP4 127.0.0.1/ }, + { output: /a=msid-semantic: WMS \*/, original: /a=msid-semantic: WMS .+/ }, + { output: /a=extmap:1\/sendrecv urn:ietf:params:rtp-hdrext:ssrc-audio-level/, original: /a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level/ }, + { output: /a=extmap:2\/sendrecv http:\/\/www.ietf.org\/id\/draft-holmer-rmcat-transport-wide-cc-extensions-01/, original: /a=extmap:2 http:\/\/www.ietf.org\/id\/draft-holmer-rmcat-transport-wide-cc-extensions-01/ }, + { output: /a=extmap:3\/sendrecv urn:ietf:params:rtp-hdrext:sdes:mid/, original: /a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid/ }, + { output: /a=extmap:4\/sendrecv urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/, original: /a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/ }, + { output: /a=extmap:5\/sendrecv urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id/, original: /a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id/ }, + { output: /a=extmap:6\/sendrecv http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/video-content-type/, original: /a=extmap:6 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/video-content-type/ }, + { output: /a=extmap:7\/sendrecv http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/video-timing/, original: /a=extmap:7 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/video-timing/ }, + { output: /a=extmap:8\/sendrecv http:\/\/tools.ietf.org\/html\/draft-ietf-avtext-framemarking-07/, original: /a=extmap:8 http:\/\/tools.ietf.org\/html\/draft-ietf-avtext-framemarking-07/ }, + { output: /a=extmap:9\/sendrecv http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/color-space/, original: /a=extmap:9 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/color-space/ }, + { output: /a=extmap:11\/sendrecv http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/playout-delay/, original: /a=extmap:11 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/playout-delay/ }, + { output: /a=extmap:12\/sendrecv urn:3gpp:video-orientation/, original: /a=extmap:12 urn:3gpp:video-orientation/ }, + { output: /a=extmap:13\/sendrecv http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time/, original: /a=extmap:13 http:\/\/www.webrtc.org\/experiments\/rtp-hdrext\/abs-send-time/ }, + { output: /a=extmap:14\/sendrecv urn:ietf:params:rtp-hdrext:toffset/, original: /a=extmap:14 urn:ietf:params:rtp-hdrext:toffset/ }, +]; + +function outputMissingLines(outputLines, originalLines) { + originalLines.forEach(function (line) { + var lineIsInOutput = outputLines.find(function (outputLine) { + return outputLine === line; + }); + + if (!lineIsInOutput) { + var matchedOverride = matchOverrides.find(function (override) { + return line.match(override.original); + }); + + // found override in the outputSdp, make sure it matches the original + if (matchedOverride) { + var matchedOutputLine = outputLines.find(function (outputLine) { + return outputLine.match(matchedOverride.output); + }); + + if (matchedOutputLine) { + return; + } + } + + console.log('"' + line + '" from originalSdp section: "' + originalLines[0] + '" cannot be found in the corresponding outputSdp'); + } + }); +} + +function validateSection(t, outputSection, originalSection) { + var outputLines = outputSection.split('\r\n'); + var originalLines = originalSection.split('\r\n'); + + t.strictEqual(outputLines.length, originalLines.length); + if (originalLines.length > outputLines.length) { + outputMissingLines(outputLines, originalLines); + } + + outputLines.forEach(function (line) { + if (!line) { + return; + } + + var lineIsInOriginal = originalLines.find(function (originalLine) { + return originalLine === line; + }); + + if (!lineIsInOriginal) { + var matchedOverride = matchOverrides.find(function (override) { + return line.match(override.output); + }); + + // found override in the outputSdp, make sure it matches the original + if (matchedOverride) { + var matchedOriginalLine = originalLines.find(function (originalLine) { + return originalLine.match(matchedOverride.original); + }); + + if (matchedOriginalLine) { + return; + } + } + + console.log(line); + originalLines; + t.fail('outputSdp line: "' + line + '" in section: "' + outputLines[0] + '" could not be found in the corresponding originalSdp section'); + } + }); +} + +// since we mangle the sdp slightly, the output sdp will be slightly different than the original input. +// this function validates the sdp and makes sure the only lines that are different are the ones we expect. +// this is especially valid since we dont guarantee ordering of certain lines of the output sdp from the json. +module.exports = function validateSdp(t, outputSdp, originalSdp) { + var outputSections = outputSdp.split(/\r?\nm=/); + var originalSections = originalSdp.split(/\r?\nm=/); + + t.equal(outputSections.length, originalSections.length); + + for (var i = 0; i < outputSections.length; i++) { + validateSection(t, outputSections[i], originalSections[i]); + } +};