pax_global_header00006660000000000000000000000064134223652700014516gustar00rootroot0000000000000052 comment=ffb0dea7c730a52ab30c9cfb11a564da43114872 sdp-jingle-json-3.1.0/000077500000000000000000000000001342236527000145225ustar00rootroot00000000000000sdp-jingle-json-3.1.0/.gitignore000066400000000000000000000000231342236527000165050ustar00rootroot00000000000000node_modules build sdp-jingle-json-3.1.0/.jshintignore000066400000000000000000000000231342236527000172210ustar00rootroot00000000000000node_modules build sdp-jingle-json-3.1.0/.jshintrc000066400000000000000000000004001342236527000163410ustar00rootroot00000000000000{ "asi": false, "expr": true, "loopfunc": true, "curly": false, "evil": true, "white": true, "undef": true, "browser": true, "node": true, "trailing": true, "indent": 4, "latedef": true, "newcap": true } sdp-jingle-json-3.1.0/.travis.yml000066400000000000000000000000621342236527000166310ustar00rootroot00000000000000sudo: false language: node_js node_js: - '0.10' sdp-jingle-json-3.1.0/CONTRIBUTING.md000066400000000000000000000013171342236527000167550ustar00rootroot00000000000000# Contributing ## Issues Feel free to submit bug reports or pull requests. If you have a security related issue, please see the [Security Guidelines](SECURITY.md) first. ## Pull Requests For any code changes, please ensure that: - The latest master branch has been incorporated in your branch - JSHint is happy - All current tests pass - All new tests (there are new tests, right?) pass The git pre-commit hook should catch most of the above issues if you run `npm install` first to set it up. ## Licensing All contributions MUST be submitted under the MIT license. Please do not contribute code that you did not write, unless you are certain you have the authorization to both do so and release it under MIT. sdp-jingle-json-3.1.0/Gruntfile.js000066400000000000000000000017041342236527000170210ustar00rootroot00000000000000"use strict"; module.exports = function (grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), browserify: { options: { standalone: 'SJJ' }, dist: { files: { 'build/<%= pkg.name %>.bundle.js': ['<%= pkg.main %>'] } } }, uglify: { dist: { files: { 'build/<%= pkg.name %>.bundle.min.js': ['build/<%= pkg.name %>.bundle.js'] } } }, jshint: { files: ['Gruntfile.js', 'index.js', 'lib/**.js', 'test/**.js'], options: grunt.file.readJSON('.jshintrc') } }); grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.registerTask('default', ['jshint', 'browserify', 'uglify']); }; sdp-jingle-json-3.1.0/LICENSE000066400000000000000000000041041342236527000155260ustar00rootroot00000000000000Copyright (c) 2013 Lance Stout Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Copyright (c) 2012-2013 ESTOS GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. sdp-jingle-json-3.1.0/README.md000066400000000000000000000134221342236527000160030ustar00rootroot00000000000000# SDP-Jingle-JSON **Convert SDP blobs to and from JSON** [![Build Status](https://travis-ci.org/otalk/sdp-jingle-json.png)](https://travis-ci.org/otalk/sdp-jingle-json) [![Dependency Status](https://david-dm.org/otalk/sdp-jingle-json.png)](https://david-dm.org/otalk/sdp-jingle-json) [![devDependency Status](https://david-dm.org/otalk/sdp-jingle-json/dev-status.png)](https://david-dm.org/otalk/sdp-jingle-json#info=devDependencies) [![Browser Support](https://ci.testling.com/otalk/sdp-jingle-json.png)](https://ci.testling.com/otalk/sdp-jingle-json) ## What is this? Ever taken a peek at the data blobs that get sent back and forth in WebRTC signalling? Yeah, that mess of line-oriented data is SDP. But sometimes you want to have that data available in JSON, like if you want to use XMPP Jingle for signalling. This library will convert raw SDP into JSON that mirrors the structure of XMPP Jingle content, making it simple to convert the SDP data into an XMPP stanza with any of the various JS XMPP libraries, such as [stanza.io](https://github.com/otalk/stanza.io), or [xmpp-ftw](https://github.com/lloydwatkin/xmpp-ftw). And since you're working with WebRTC, be sure to check out [simplewebrtc](http://simplewebrtc.com). ## Installing ``` npm install sdp-jingle-json ``` ## Building bundled/minified version (for AMD, etc) ```sh $ grunt ``` The bundled and minified files will be in the generated `build` directory. ## How to use it ``` var sjj = require('sdp-jingle-json'); // I have SDP, but want JSON: var json = sjj.toSessionJSON(sdpBlob, { creators: ['initiator', 'initiator'], // Who created the media contents role: 'initiator', // Which side of the offer/answer are we acting as direction: 'outgoing' // Are we parsing SDP that we are sending or receiving? }); // I have JSON (a dictionary of session and content descriptions), but want SDP: var sdp = sjj.toSessionSDP(jsonSession, { role: 'responder', direction: 'incoming' }); ``` You can also use `toMediaSDP` and `toMediaJSON` to convert only a single media section. ## See it in action Open the `convert.html` file and enter in SDP or JSON to see how it converts back and forth. ## Jingle JSON The format for the generated JSON content is: ``` { "action": "", "initiator": "", "responder": "", "sid": "", // ---- Content payload "groups": [ { "semantics": "", "contents": [], } //... ], "contents": [ { "name": "", "creator": "", "senders": "", "application": { // ---- RTP description "applicationType": "rtp", "media": "", "ssrc": "", "sourceGroups": [ { "semantics": "", "sources": [ "" //... ] } //... ], "sources": [ { "ssrc": "", "parameters: [ { "key": "", "value": "" } //... ] } //... ], "bandwidth": "", "bandwidthType": "", "headerExtensions": [ { "id": "", "uri": "", "senders": "" } //... ], "payloads": [ { "id": "", "channels": "", "clockrate": "", "maxptime": "", "ptime": "", "name": "", "parameters": [ { "key": "", "value": "" } //... ], "feedback": [ { "type": "", "subtype": "", "value": "" } //... ] } ], "encryption": [ { "cipherSuite": "", "keyParams": "", "sessionParams": "", "tag": "" } //... ] }, "transport": { // ---- ICE UDP transport "transportType": "iceUdp", "ufrag": "", "pwd": "", "setup": "", "candidates": [ { "component": "", "foundation": "", "generation": "", "id": "", "ip": "", "network": "", "port": "", "priority": "", "protocol": "", "relAddr": "", "relPort": "", "type": "" } //... ], "fingerprints": [ { "hash": "", "value": "" } // ... ] } } //... ] } ``` ## License MIT ## Created By If you like this, follow [@lancestout](http://twitter.com/lancestout) or [@HCornflower](http://twitter.com/HCornflower) on twitter. SDP-Jingle-JSON is derived, in collaboration, from the work done by Philipp Hancke for [strophe.jingle](https://github.com/estos/strophe.jingle). sdp-jingle-json-3.1.0/SECURITY.md000066400000000000000000000006351342236527000163170ustar00rootroot00000000000000# Reporting Security Issues [Report Vulnerability to the Node Security Project](mailto:report@nodesecurity.io?cc=lancestout@gmail.com&subject=Security%20Issue%20for%20SDP-Jingle-JSON) In the interest of responsible disclosure, please use the above to report any security issues so that the appropriate patches and advisories can be made. ## History No security issues have been reported for this project yet. sdp-jingle-json-3.1.0/convert.html000066400000000000000000000026001342236527000170660ustar00rootroot00000000000000 SDP JSON converter sdp-jingle-json-3.1.0/index.js000066400000000000000000000062261342236527000161750ustar00rootroot00000000000000var toSDP = require('./lib/tosdp'); var toJSON = require('./lib/tojson'); // Converstion from JSON to SDP exports.toIncomingSDPOffer = function (session) { return toSDP.toSessionSDP(session, { role: 'responder', direction: 'incoming' }); }; exports.toOutgoingSDPOffer = function (session) { return toSDP.toSessionSDP(session, { role: 'initiator', direction: 'outgoing' }); }; exports.toIncomingSDPAnswer = function (session) { return toSDP.toSessionSDP(session, { role: 'initiator', direction: 'incoming' }); }; exports.toOutgoingSDPAnswer = function (session) { return toSDP.toSessionSDP(session, { role: 'responder', direction: 'outgoing' }); }; exports.toIncomingMediaSDPOffer = function (media) { return toSDP.toMediaSDP(media, { role: 'responder', direction: 'incoming' }); }; exports.toOutgoingMediaSDPOffer = function (media) { return toSDP.toMediaSDP(media, { role: 'initiator', direction: 'outgoing' }); }; exports.toIncomingMediaSDPAnswer = function (media) { return toSDP.toMediaSDP(media, { role: 'initiator', direction: 'incoming' }); }; exports.toOutgoingMediaSDPAnswer = function (media) { return toSDP.toMediaSDP(media, { role: 'responder', direction: 'outgoing' }); }; exports.toCandidateSDP = toSDP.toCandidateSDP; exports.toMediaSDP = toSDP.toMediaSDP; exports.toSessionSDP = toSDP.toSessionSDP; // Conversion from SDP to JSON exports.toIncomingJSONOffer = function (sdp, creators) { return toJSON.toSessionJSON(sdp, { role: 'responder', direction: 'incoming', creators: creators }); }; exports.toOutgoingJSONOffer = function (sdp, creators) { return toJSON.toSessionJSON(sdp, { role: 'initiator', direction: 'outgoing', creators: creators }); }; exports.toIncomingJSONAnswer = function (sdp, creators) { return toJSON.toSessionJSON(sdp, { role: 'initiator', direction: 'incoming', creators: creators }); }; exports.toOutgoingJSONAnswer = function (sdp, creators) { return toJSON.toSessionJSON(sdp, { role: 'responder', direction: 'outgoing', creators: creators }); }; exports.toIncomingMediaJSONOffer = function (sdp, creator) { return toJSON.toMediaJSON(sdp, { role: 'responder', direction: 'incoming', creator: creator }); }; exports.toOutgoingMediaJSONOffer = function (sdp, creator) { return toJSON.toMediaJSON(sdp, { role: 'initiator', direction: 'outgoing', creator: creator }); }; exports.toIncomingMediaJSONAnswer = function (sdp, creator) { return toJSON.toMediaJSON(sdp, { role: 'initiator', direction: 'incoming', creator: creator }); }; exports.toOutgoingMediaJSONAnswer = function (sdp, creator) { return toJSON.toMediaJSON(sdp, { role: 'responder', direction: 'outgoing', creator: creator }); }; exports.toCandidateJSON = toJSON.toCandidateJSON; exports.toMediaJSON = toJSON.toMediaJSON; exports.toSessionJSON = toJSON.toSessionJSON; sdp-jingle-json-3.1.0/lib/000077500000000000000000000000001342236527000152705ustar00rootroot00000000000000sdp-jingle-json-3.1.0/lib/parsers.js000066400000000000000000000147061342236527000173150ustar00rootroot00000000000000exports.lines = function (sdp) { return sdp.split(/\r?\n/).filter(function (line) { return line.length > 0; }); }; exports.findLine = function (prefix, mediaLines, sessionLines) { var prefixLength = prefix.length; for (var i = 0; i < mediaLines.length; i++) { if (mediaLines[i].substr(0, prefixLength) === prefix) { return mediaLines[i]; } } // Continue searching in parent session section if (!sessionLines) { return false; } for (var j = 0; j < sessionLines.length; j++) { if (sessionLines[j].substr(0, prefixLength) === prefix) { return sessionLines[j]; } } return false; }; exports.findLines = function (prefix, mediaLines, sessionLines) { var results = []; var prefixLength = prefix.length; for (var i = 0; i < mediaLines.length; i++) { if (mediaLines[i].substr(0, prefixLength) === prefix) { results.push(mediaLines[i]); } } if (results.length || !sessionLines) { return results; } for (var j = 0; j < sessionLines.length; j++) { if (sessionLines[j].substr(0, prefixLength) === prefix) { results.push(sessionLines[j]); } } return results; }; exports.mline = function (line) { var parts = line.substr(2).split(' '); var parsed = { media: parts[0], port: parts[1], proto: parts[2], formats: [] }; for (var i = 3; i < parts.length; i++) { if (parts[i]) { parsed.formats.push(parts[i]); } } return parsed; }; exports.rtpmap = function (line) { var parts = line.substr(9).split(' '); var parsed = { id: parts.shift() }; parts = parts[0].split('/'); parsed.name = parts[0]; parsed.clockrate = parts[1]; parsed.channels = parts.length == 3 ? parts[2] : '1'; return parsed; }; exports.sctpmap = function (line) { // based on -05 draft var parts = line.substr(10).split(' '); var parsed = { number: parts.shift(), protocol: parts.shift(), streams: parts.shift() }; return parsed; }; exports.fmtp = function (line) { var kv, key, value; var parts = line.substr(line.indexOf(' ') + 1).split(';'); var parsed = []; for (var i = 0; i < parts.length; i++) { kv = parts[i].split('='); key = kv[0].trim(); value = kv[1]; if (key && value) { parsed.push({key: key, value: value}); } else if (key) { parsed.push({key: '', value: key}); } } return parsed; }; exports.crypto = function (line) { var parts = line.substr(9).split(' '); var parsed = { tag: parts[0], cipherSuite: parts[1], keyParams: parts[2], sessionParams: parts.slice(3).join(' ') }; return parsed; }; exports.fingerprint = function (line) { var parts = line.substr(14).split(' '); return { hash: parts[0], value: parts[1] }; }; exports.extmap = function (line) { var parts = line.substr(9).split(' '); var parsed = {}; var idpart = parts.shift(); var sp = idpart.indexOf('/'); if (sp >= 0) { parsed.id = idpart.substr(0, sp); parsed.senders = idpart.substr(sp + 1); } else { parsed.id = idpart; parsed.senders = 'sendrecv'; } parsed.uri = parts.shift() || ''; return parsed; }; exports.rtcpfb = function (line) { var parts = line.substr(10).split(' '); var parsed = {}; parsed.id = parts.shift(); parsed.type = parts.shift(); if (parsed.type === 'trr-int') { parsed.value = parts.shift(); } else { parsed.subtype = parts.shift() || ''; } parsed.parameters = parts; return parsed; }; exports.candidate = function (line) { var parts; if (line.indexOf('a=candidate:') === 0) { parts = line.substring(12).split(' '); } else { // no a=candidate parts = line.substring(10).split(' '); } var candidate = { foundation: parts[0], component: parts[1], protocol: parts[2].toLowerCase(), priority: parts[3], ip: parts[4], port: parts[5], // skip parts[6] == 'typ' type: parts[7], generation: '0' }; for (var i = 8; i < parts.length; i += 2) { if (parts[i] === 'raddr') { candidate.relAddr = parts[i + 1]; } else if (parts[i] === 'rport') { candidate.relPort = parts[i + 1]; } else if (parts[i] === 'generation') { candidate.generation = parts[i + 1]; } else if (parts[i] === 'tcptype') { candidate.tcpType = parts[i + 1]; } } candidate.network = '1'; return candidate; }; exports.sourceGroups = function (lines) { var parsed = []; for (var i = 0; i < lines.length; i++) { var parts = lines[i].substr(13).split(' '); parsed.push({ semantics: parts.shift(), sources: parts }); } return parsed; }; exports.sources = function (lines) { // http://tools.ietf.org/html/rfc5576 var parsed = []; var sources = {}; for (var i = 0; i < lines.length; i++) { var parts = lines[i].substr(7).split(' '); var ssrc = parts.shift(); if (!sources[ssrc]) { var source = { ssrc: ssrc, parameters: [] }; parsed.push(source); // Keep an index sources[ssrc] = source; } parts = parts.join(' ').split(':'); var attribute = parts.shift(); var value = parts.join(':') || null; sources[ssrc].parameters.push({ key: attribute, value: value }); } return parsed; }; exports.groups = function (lines) { // http://tools.ietf.org/html/rfc5888 var parsed = []; var parts; for (var i = 0; i < lines.length; i++) { parts = lines[i].substr(8).split(' '); parsed.push({ semantics: parts.shift(), contents: parts }); } return parsed; }; exports.bandwidth = function (line) { var parts = line.substr(2).split(':'); var parsed = {}; parsed.type = parts.shift(); parsed.bandwidth = parts.shift(); return parsed; }; exports.msid = function (line) { var data = line.substr(7); var parts = data.split(' '); return { msid: data, mslabel: parts[0], label: parts[1] }; }; sdp-jingle-json-3.1.0/lib/senders.js000066400000000000000000000023131342236527000172700ustar00rootroot00000000000000module.exports = { initiator: { incoming: { initiator: 'recvonly', responder: 'sendonly', both: 'sendrecv', none: 'inactive', recvonly: 'initiator', sendonly: 'responder', sendrecv: 'both', inactive: 'none' }, outgoing: { initiator: 'sendonly', responder: 'recvonly', both: 'sendrecv', none: 'inactive', recvonly: 'responder', sendonly: 'initiator', sendrecv: 'both', inactive: 'none' } }, responder: { incoming: { initiator: 'sendonly', responder: 'recvonly', both: 'sendrecv', none: 'inactive', recvonly: 'responder', sendonly: 'initiator', sendrecv: 'both', inactive: 'none' }, outgoing: { initiator: 'recvonly', responder: 'sendonly', both: 'sendrecv', none: 'inactive', recvonly: 'initiator', sendonly: 'responder', sendrecv: 'both', inactive: 'none' } } }; sdp-jingle-json-3.1.0/lib/tojson.js000066400000000000000000000163551342236527000171540ustar00rootroot00000000000000var SENDERS = require('./senders'); var parsers = require('./parsers'); var idCounter = Math.random(); exports._setIdCounter = function (counter) { idCounter = counter; }; exports.toSessionJSON = function (sdp, opts) { var i; var creators = opts.creators || []; var role = opts.role || 'initiator'; var direction = opts.direction || 'outgoing'; // Divide the SDP into session and media sections. var media = sdp.split(/\r?\nm=/); for (i = 1; i < media.length; i++) { media[i] = 'm=' + media[i]; if (i !== media.length - 1) { media[i] += '\r\n'; } } var session = media.shift() + '\r\n'; var sessionLines = parsers.lines(session); var parsed = {}; var contents = []; for (i = 0; i < media.length; i++) { contents.push(exports.toMediaJSON(media[i], session, { role: role, direction: direction, creator: creators[i] || 'initiator' })); } parsed.contents = contents; var groupLines = parsers.findLines('a=group:', sessionLines); if (groupLines.length) { parsed.groups = parsers.groups(groupLines); } return parsed; }; exports.toMediaJSON = function (media, session, opts) { var creator = opts.creator || 'initiator'; var role = opts.role || 'initiator'; var direction = opts.direction || 'outgoing'; var lines = parsers.lines(media); var sessionLines = parsers.lines(session); var mline = parsers.mline(lines[0]); var content = { creator: creator, name: mline.media, application: { applicationType: 'rtp', media: mline.media, payloads: [], encryption: [], feedback: [], headerExtensions: [] }, transport: { transportType: 'iceUdp', candidates: [], fingerprints: [] } }; 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 content.application = { applicationType: 'datachannel' }; content.transport.sctp = []; } var desc = content.application; var trans = content.transport; // If we have a mid, use that for the content name instead. var mid = parsers.findLine('a=mid:', lines); if (mid) { content.name = mid.substr(6); } if (parsers.findLine('a=sendrecv', lines, sessionLines)) { content.senders = 'both'; } else if (parsers.findLine('a=sendonly', lines, sessionLines)) { content.senders = SENDERS[role][direction].sendonly; } else if (parsers.findLine('a=recvonly', lines, sessionLines)) { content.senders = SENDERS[role][direction].recvonly; } else if (parsers.findLine('a=inactive', lines, sessionLines)) { content.senders = 'none'; } if (desc.applicationType == 'rtp') { var bandwidth = parsers.findLine('b=', lines); if (bandwidth) { desc.bandwidth = parsers.bandwidth(bandwidth); } var ssrc = parsers.findLine('a=ssrc:', lines); if (ssrc) { desc.ssrc = ssrc.substr(7).split(' ')[0]; } var rtpmapLines = parsers.findLines('a=rtpmap:', lines); rtpmapLines.forEach(function (line) { var payload = parsers.rtpmap(line); payload.parameters = []; payload.feedback = []; var fmtpLines = parsers.findLines('a=fmtp:' + payload.id, lines); // There should only be one fmtp line per payload fmtpLines.forEach(function (line) { payload.parameters = parsers.fmtp(line); }); var fbLines = parsers.findLines('a=rtcp-fb:' + payload.id, lines); fbLines.forEach(function (line) { payload.feedback.push(parsers.rtcpfb(line)); }); desc.payloads.push(payload); }); var cryptoLines = parsers.findLines('a=crypto:', lines, sessionLines); cryptoLines.forEach(function (line) { desc.encryption.push(parsers.crypto(line)); }); if (parsers.findLine('a=rtcp-mux', lines)) { desc.mux = true; } if (parsers.findLine('a=rtcp-rsize', lines)) { desc.rsize = true; } var fbLines = parsers.findLines('a=rtcp-fb:*', lines); fbLines.forEach(function (line) { desc.feedback.push(parsers.rtcpfb(line)); }); var extLines = parsers.findLines('a=extmap:', lines); extLines.forEach(function (line) { var ext = parsers.extmap(line); ext.senders = SENDERS[role][direction][ext.senders]; desc.headerExtensions.push(ext); }); var ssrcGroupLines = parsers.findLines('a=ssrc-group:', lines); desc.sourceGroups = parsers.sourceGroups(ssrcGroupLines || []); var ssrcLines = parsers.findLines('a=ssrc:', lines); var sources = desc.sources = parsers.sources(ssrcLines || []); var msidLine = parsers.findLine('a=msid:', lines); if (msidLine) { var msid = parsers.msid(msidLine); ['msid', 'mslabel', 'label'].forEach(function (key) { for (var i = 0; i < sources.length; i++) { var found = false; for (var j = 0; j < sources[i].parameters.length; j++) { if (sources[i].parameters[j].key === key) { found = true; } } if (!found) { sources[i].parameters.push({ key: key, value: msid[key] }); } } }); } if (parsers.findLine('a=x-google-flag:conference', lines, sessionLines)) { desc.googConferenceFlag = true; } } // transport specific attributes var fingerprintLines = parsers.findLines('a=fingerprint:', lines, sessionLines); var setup = parsers.findLine('a=setup:', lines, sessionLines); fingerprintLines.forEach(function (line) { var fp = parsers.fingerprint(line); if (setup) { fp.setup = setup.substr(8); } trans.fingerprints.push(fp); }); var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines); var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines); if (ufragLine && pwdLine) { trans.ufrag = ufragLine.substr(12); trans.pwd = pwdLine.substr(10); trans.candidates = []; var candidateLines = parsers.findLines('a=candidate:', lines, sessionLines); candidateLines.forEach(function (line) { trans.candidates.push(exports.toCandidateJSON(line)); }); } if (desc.applicationType == 'datachannel') { var sctpmapLines = parsers.findLines('a=sctpmap:', lines); sctpmapLines.forEach(function (line) { var sctp = parsers.sctpmap(line); trans.sctp.push(sctp); }); } return content; }; exports.toCandidateJSON = function (line) { var candidate = parsers.candidate(line.split(/\r?\n/)[0]); candidate.id = (idCounter++).toString(36).substr(0, 12); return candidate; }; sdp-jingle-json-3.1.0/lib/tosdp.js000066400000000000000000000171011342236527000167570ustar00rootroot00000000000000var SENDERS = require('./senders'); exports.toSessionSDP = function (session, opts) { var role = opts.role || 'initiator'; var direction = opts.direction || 'outgoing'; var sid = opts.sid || session.sid || Date.now(); var time = opts.time || Date.now(); var sdp = [ 'v=0', 'o=- ' + sid + ' ' + time + ' IN IP4 0.0.0.0', 's=-', 't=0 0' ]; var contents = session.contents || []; var hasSources = false; contents.forEach(function (content) { if (content.application.sources && content.application.sources.length) { hasSources = true; } }); if (hasSources) { sdp.push('a=msid-semantic: WMS *'); } var groups = session.groups || []; groups.forEach(function (group) { sdp.push('a=group:' + group.semantics + ' ' + group.contents.join(' ')); }); contents.forEach(function (content) { sdp.push(exports.toMediaSDP(content, opts)); }); return sdp.join('\r\n') + '\r\n'; }; exports.toMediaSDP = function (content, opts) { var sdp = []; var role = opts.role || 'initiator'; var direction = opts.direction || 'outgoing'; var desc = content.application; var transport = content.transport; var payloads = desc.payloads || []; var fingerprints = (transport && transport.fingerprints) || []; var mline = []; if (desc.applicationType == 'datachannel') { mline.push('application'); mline.push('1'); mline.push('DTLS/SCTP'); if (transport.sctp) { transport.sctp.forEach(function (map) { mline.push(map.number); }); } } else { mline.push(desc.media); mline.push('1'); if (fingerprints.length > 0) { mline.push('UDP/TLS/RTP/SAVPF'); } else if (desc.encryption && desc.encryption.length > 0) { mline.push('RTP/SAVPF'); } else { mline.push('RTP/AVPF'); } payloads.forEach(function (payload) { mline.push(payload.id); }); } sdp.push('m=' + mline.join(' ')); sdp.push('c=IN IP4 0.0.0.0'); if (desc.bandwidth && desc.bandwidth.type && desc.bandwidth.bandwidth) { sdp.push('b=' + desc.bandwidth.type + ':' + desc.bandwidth.bandwidth); } if (desc.applicationType == 'rtp') { sdp.push('a=rtcp:1 IN IP4 0.0.0.0'); } if (transport) { if (transport.ufrag) { sdp.push('a=ice-ufrag:' + transport.ufrag); } if (transport.pwd) { sdp.push('a=ice-pwd:' + transport.pwd); } var pushedSetup = false; fingerprints.forEach(function (fingerprint) { sdp.push('a=fingerprint:' + fingerprint.hash + ' ' + fingerprint.value); if (fingerprint.setup && !pushedSetup) { sdp.push('a=setup:' + fingerprint.setup); } }); if (transport.sctp) { transport.sctp.forEach(function (map) { sdp.push('a=sctpmap:' + map.number + ' ' + map.protocol + ' ' + map.streams); }); } } if (desc.applicationType == 'rtp') { sdp.push('a=' + (SENDERS[role][direction][content.senders] || 'sendrecv')); } sdp.push('a=mid:' + content.name); if (desc.sources && desc.sources.length) { var streams = {}; desc.sources.forEach(function (source) { (source.parameters || []).forEach(function (param) { if (param.key === 'msid') { streams[param.value] = 1; } }); }); streams = Object.keys(streams); if (streams.length === 1) { sdp.push('a=msid:' + streams[0]); } } if (desc.mux) { sdp.push('a=rtcp-mux'); } if (desc.rsize) { sdp.push('a=rtcp-rsize'); } var encryption = desc.encryption || []; encryption.forEach(function (crypto) { sdp.push('a=crypto:' + crypto.tag + ' ' + crypto.cipherSuite + ' ' + crypto.keyParams + (crypto.sessionParams ? ' ' + crypto.sessionParams : '')); }); if (desc.googConferenceFlag) { sdp.push('a=x-google-flag:conference'); } payloads.forEach(function (payload) { var rtpmap = 'a=rtpmap:' + payload.id + ' ' + payload.name + '/' + payload.clockrate; if (payload.channels && payload.channels != '1') { rtpmap += '/' + payload.channels; } sdp.push(rtpmap); if (payload.parameters && payload.parameters.length) { var fmtp = ['a=fmtp:' + payload.id]; var parameters = []; payload.parameters.forEach(function (param) { parameters.push((param.key ? param.key + '=' : '') + param.value); }); fmtp.push(parameters.join(';')); sdp.push(fmtp.join(' ')); } if (payload.feedback) { payload.feedback.forEach(function (fb) { if (fb.type === 'trr-int') { sdp.push('a=rtcp-fb:' + payload.id + ' trr-int ' + (fb.value ? fb.value : '0')); } else { sdp.push('a=rtcp-fb:' + payload.id + ' ' + fb.type + (fb.subtype ? ' ' + fb.subtype : '')); } }); } }); if (desc.feedback) { desc.feedback.forEach(function (fb) { if (fb.type === 'trr-int') { sdp.push('a=rtcp-fb:* trr-int ' + (fb.value ? fb.value : '0')); } else { sdp.push('a=rtcp-fb:* ' + fb.type + (fb.subtype ? ' ' + fb.subtype : '')); } }); } var hdrExts = desc.headerExtensions || []; hdrExts.forEach(function (hdr) { sdp.push('a=extmap:' + hdr.id + (hdr.senders ? '/' + SENDERS[role][direction][hdr.senders] : '') + ' ' + hdr.uri); }); var ssrcGroups = desc.sourceGroups || []; ssrcGroups.forEach(function (ssrcGroup) { sdp.push('a=ssrc-group:' + ssrcGroup.semantics + ' ' + ssrcGroup.sources.join(' ')); }); var ssrcs = desc.sources || []; ssrcs.forEach(function (ssrc) { for (var i = 0; i < ssrc.parameters.length; i++) { var param = ssrc.parameters[i]; sdp.push('a=ssrc:' + (ssrc.ssrc || desc.ssrc) + ' ' + param.key + (param.value ? (':' + param.value) : '')); } }); var candidates = transport.candidates || []; candidates.forEach(function (candidate) { sdp.push(exports.toCandidateSDP(candidate)); }); return sdp.join('\r\n'); }; exports.toCandidateSDP = function (candidate) { var sdp = []; sdp.push(candidate.foundation); sdp.push(candidate.component); sdp.push(candidate.protocol.toUpperCase()); sdp.push(candidate.priority); sdp.push(candidate.ip); sdp.push(candidate.port); var type = candidate.type; sdp.push('typ'); sdp.push(type); if (type === 'srflx' || type === 'prflx' || type === 'relay') { if (candidate.relAddr && candidate.relPort) { sdp.push('raddr'); sdp.push(candidate.relAddr); sdp.push('rport'); sdp.push(candidate.relPort); } } if (candidate.tcpType && candidate.protocol.toUpperCase() == 'TCP') { sdp.push('tcptype'); sdp.push(candidate.tcpType); } sdp.push('generation'); sdp.push(candidate.generation || '0'); // FIXME: apparently this is wrong per spec // but then, we need this when actually putting this into // SDP so it's going to stay. // decision needs to be revisited when browsers dont // accept this any longer return 'a=candidate:' + sdp.join(' '); }; sdp-jingle-json-3.1.0/package.json000066400000000000000000000023271342236527000170140ustar00rootroot00000000000000{ "name": "sdp-jingle-json", "version": "3.1.0", "description": "A parser/serializer for SDP to JSON. Useful for converting SDP to other formats like Jingle for WebRTC signalling", "main": "index.js", "repository": { "type": "git", "url": "https://github.com/legastero/sdp-jingle-json.git" }, "bugs": "https://github.com/legastero/sdp-jingle-json/issues", "keywords": [ "sdp", "webrtc", "xmpp", "jingle" ], "contributors": [ "Lance Stout ", "Philipp Hancke " ], "license": "MIT", "dependencies": {}, "devDependencies": { "browserify": "2.36.1", "grunt": "0.4.2", "grunt-browserify": "1.2.11", "grunt-contrib-jshint": "0.7.2", "grunt-contrib-uglify": "0.2.7", "precommit-hook": "0.3.8", "tape": "2.3.0" }, "testling": { "files": [ "test/test.js" ], "browsers": [ "ie/10..latest", "chrome/20..latest", "chrome/canary", "firefox/10..latest", "firefox/nightly", "opera/next", "safari/6..latest", "iphone/6..latest", "ipad/6..latest", "android-browser/4.2..latest" ] }, "scripts": { "test": "node test/test.js" } } sdp-jingle-json-3.1.0/test/000077500000000000000000000000001342236527000155015ustar00rootroot00000000000000sdp-jingle-json-3.1.0/test/data/000077500000000000000000000000001342236527000164125ustar00rootroot00000000000000sdp-jingle-json-3.1.0/test/data/json.js000066400000000000000000000273151342236527000177310ustar00rootroot00000000000000module.exports = { "contents": [ { "creator": "initiator", "name": "audio", "application": { "applicationType": "rtp", "media": "audio", "payloads": [ { "id": "111", "name": "opus", "clockrate": "48000", "channels": "2", "feedback": [], "parameters": [ { "key": "minptime", "value": "10" } ] }, { "id": "103", "name": "ISAC", "clockrate": "16000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "104", "name": "ISAC", "clockrate": "32000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "0", "name": "PCMU", "clockrate": "8000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "8", "name": "PCMA", "clockrate": "8000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "107", "name": "CN", "clockrate": "48000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "106", "name": "CN", "clockrate": "32000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "105", "name": "CN", "clockrate": "16000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "13", "name": "CN", "clockrate": "8000", "channels": "1", "feedback": [], "parameters": [] }, { "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": "" } ], "feedback": [], "headerExtensions": [ { "id": "1", "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level", "senders": "both" } ], "ssrc": "445948959", "mux": true, "rsize": true, "sourceGroups": [], "sources": [ { "ssrc": "445948959", "parameters": [ { "key": "cname", "value": "RbR04HtIjW+Sa+yz" }, { "key": "msid", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0" }, { "key": "mslabel", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" }, { "key": "label", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0" } ] } ] }, "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" } ], "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" } ], "ufrag": "TESg/uYDt8nNomZd", "pwd": "abQXlDvFdLKIVdRDdg1t5Tbn" }, "senders": "both" }, { "creator": "initiator", "name": "video", "application": { "applicationType": "rtp", "media": "video", "payloads": [ { "id": "100", "name": "VP8", "clockrate": "90000", "channels": "1", "feedback": [ { "id": "100", "type": "ccm", "subtype": "fir", "parameters": [] }, { "id": "100", "type": "nack", "subtype": "", "parameters": [] }, { "id": "100", "type": "goog-remb", "subtype": "", "parameters": [] } ], "parameters": [] }, { "id": "116", "name": "red", "clockrate": "90000", "channels": "1", "feedback": [], "parameters": [] }, { "id": "117", "name": "ulpfec", "clockrate": "90000", "channels": "1", "feedback": [], "parameters": [] } ], "encryption": [ { "tag": "1", "cipherSuite": "AES_CM_128_HMAC_SHA1_80", "keyParams": "inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", "sessionParams": "" } ], "feedback": [], "headerExtensions": [ { "id": "2", "uri": "urn:ietf:params:rtp-hdrext:toffset", "senders": "both" } ], "ssrc": "797563643", "mux": true, "sourceGroups": [ { "semantics": "FID", "sources": ["797563643", "193463643"] } ], "sources": [ { "ssrc": "797563643", "parameters": [ { "key": "cname", "value": "RbR04HtIjW+Sa+yz" }, { "key": "msid", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" }, { "key": "mslabel", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" }, { "key": "label", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" } ] }, { "ssrc": "193463643", "parameters": [ { "key": "cname", "value": "RbR04HtIjW+Sa+yz" }, { "key": "msid", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" }, { "key": "mslabel", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo" }, { "key": "label", "value": "uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0" } ] } ] }, "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" } ], "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" } ], "ufrag": "TESg/uYDt8nNomZd", "pwd": "abQXlDvFdLKIVdRDdg1t5Tbn" }, "senders": "both" } ], "groups": [ { "semantics": "BUNDLE", "contents": [ "audio", "video" ] } ] }; sdp-jingle-json-3.1.0/test/data/no-source-json.js000066400000000000000000000054421342236527000216360ustar00rootroot00000000000000module.exports = { "contents": [ { "creator": "initiator", "name": "audio", "application": { "applicationType": "rtp", "media": "audio", "payloads": [ { "id": "96", "name": "opus", "clockrate": "48000", "channels": "2", "parameters": [], "feedback": [] }, { "id": "101", "name": "telephone-event", "clockrate": "48000", "channels": "1", "parameters": [ { "key": "bitrate", "value": "0" } ], "feedback": [] } ], "encryption": [], "feedback": [], "headerExtensions": [], "sourceGroups": [], "sources": [] }, "transport": { "transportType": "iceUdp", "candidates": [ { "foundation": "1", "component": "1", "protocol": "udp", "priority": "0", "ip": "xx.xx.xxx.xxx", "port": "27622", "type": "host", "generation": "0", "network": "1", "id": "0" }, { "foundation": "1974206464", "component": "1", "protocol": "udp", "priority": "1694498815", "ip": "xxx.xx.xxx.xxx", "port": "27622", "type": "srflx", "generation": "0", "relAddr": "xx.xx.xxx.xxx", "relPort": "27622", "network": "1", "id": "1" } ], "fingerprints": [ { "hash": "sha-256", "value": "A1:D1:E8:C0:A3:B2:66:AA:8E:40:46:F0:4F:FE:FB:B9:99:82:E3:D9:6B:C9:F4:11:64:5E:AD:54:99:2C:E3:03", "setup": "actpass" } ], "ufrag": "GXUH9ptTQlZT2f1l", "pwd": "6AWVYDmAkCyeBQeG75QCC6TE" }, "senders": "both" } ] }; sdp-jingle-json-3.1.0/test/data/no-source-sdp.js000066400000000000000000000014541342236527000214520ustar00rootroot00000000000000module.exports = [ "v=0", "o=- 1382398245712 1385147470924 IN IP4 0.0.0.0", "s=-", "t=0 0", "m=audio 1 UDP/TLS/RTP/SAVPF 96 101", "c=IN IP4 0.0.0.0", "a=rtcp:1 IN IP4 0.0.0.0", "a=ice-ufrag:GXUH9ptTQlZT2f1l", "a=ice-pwd:6AWVYDmAkCyeBQeG75QCC6TE", "a=fingerprint:sha-256 A1:D1:E8:C0:A3:B2:66:AA:8E:40:46:F0:4F:FE:FB:B9:99:82:E3:D9:6B:C9:F4:11:64:5E:AD:54:99:2C:E3:03", "a=setup:actpass", "a=sendrecv", "a=mid:audio", "a=rtpmap:96 opus/48000/2", "a=rtpmap:101 telephone-event/48000", "a=fmtp:101 bitrate=0", "a=candidate:1 1 UDP 0 xx.xx.xxx.xxx 27622 typ host generation 0", "a=candidate:1974206464 1 UDP 1694498815 xxx.xx.xxx.xxx 27622 typ srflx raddr xx.xx.xxx.xxx rport 27622 generation 0", "" // So we end with a \r\n ].join('\r\n'); sdp-jingle-json-3.1.0/test/data/sdp.js000066400000000000000000000060131342236527000175360ustar00rootroot00000000000000module.exports = [ "v=0", "o=- 1382398245712 1385147470924 IN IP4 0.0.0.0", "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", "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=sendrecv", "a=mid:audio", "a=msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgoa0", "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=rtpmap:103 ISAC/16000", "a=rtpmap:104 ISAC/32000", "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: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", "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=sendrecv", "a=mid:video", "a=msid:uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgo uwwsnlQmzOrjxCsin4Z5lQ5XVpUFHQgUYLgov0", "a=rtcp-mux", "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:EwN4nicDelI9pradqeXwjvJVjhIZthVgukUu33Of", "a=rtpmap:100 VP8/90000", "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", "" // So we end with a \r\n ].join('\r\n'); sdp-jingle-json-3.1.0/test/npm-debug.log000066400000000000000000000015071342236527000200650ustar00rootroot000000000000000 info it worked if it ends with ok 1 verbose cli [ '/Users/lance/.nvm/v0.10.21/bin/node', 1 verbose cli '/Users/lance/.nvm/v0.10.21/bin/npm', 1 verbose cli 'test' ] 2 info using npm@1.3.11 3 info using node@v0.10.21 4 error Error: ENOENT, open '/Users/lance/Projects/sdp-jingle-json/test/package.json' 5 error If you need help, you may report this log at: 5 error 5 error or email it to: 5 error 6 error System Darwin 13.0.1 7 error command "/Users/lance/.nvm/v0.10.21/bin/node" "/Users/lance/.nvm/v0.10.21/bin/npm" "test" 8 error cwd /Users/lance/Projects/sdp-jingle-json/test 9 error node -v v0.10.21 10 error npm -v 1.3.11 11 error path /Users/lance/Projects/sdp-jingle-json/test/package.json 12 error code ENOENT 13 error errno 34 14 verbose exit [ 34, true ] sdp-jingle-json-3.1.0/test/test.js000066400000000000000000000043311342236527000170170ustar00rootroot00000000000000"use strict"; var fs = require('fs'); var test = require('tape'); var SJJ = require('../index'); var tojson = require('../lib/tojson'); var jsonData = require('./data/json'); var sdpData = require('./data/sdp'); var noSourceSdpData = require('./data/no-source-sdp'); var noSourceJsonData = require('./data/no-source-json'); // Data that is typically unique or time dependent var sid = '1382398245712'; var time = '1385147470924'; test('to json', function (t) { tojson._setIdCounter(0); var json = SJJ.toSessionJSON(sdpData, { creator: 'initiator', role: 'initiator', direction: 'outgoing' }); t.deepEqual(json, jsonData); t.end(); }); test('to sdp', function (t) { var sdp = SJJ.toSessionSDP(jsonData, { role: 'initiator', direction: 'outgoing', sid: sid, time: time }); t.deepEqual(sdp, sdpData); t.end(); }); test('no source to json', function (t) { tojson._setIdCounter(0); var json = SJJ.toSessionJSON(noSourceSdpData, { creator: 'initiator', role: 'initiator', direction: 'outgoing' }); t.deepEqual(json, noSourceJsonData); t.end(); }); test('no source to sdp', function (t) { t.plan(2); var sdp = SJJ.toSessionSDP(noSourceJsonData, { role: 'initiator', direction: 'outgoing', sid: sid, time: time }); t.ok(sdp.indexOf('msid-semantic') === -1); t.deepEqual(sdp, noSourceSdpData); t.end(); }); test('multiple pases', function (t) { t.plan(2); tojson._setIdCounter(0); var json1 = SJJ.toSessionJSON(sdpData, { creator: 'initiator', role: 'initiator', direction: 'outgoing' }); var sdp1 = SJJ.toSessionSDP(json1, { role: 'initiator', direction: 'outgoing', sid: sid, time: time }); tojson._setIdCounter(0); var json2 = SJJ.toSessionJSON(sdp1, { creator: 'initiator', role: 'initiator', direction: 'outgoing' }); var sdp2 = SJJ.toSessionSDP(json2, { role: 'initiator', direction: 'outgoing', sid: sid, time: time }); t.deepEqual(json2, jsonData); t.deepEqual(sdp2, sdpData); t.end(); });