diff --git a/strophe.jinglejs-bundle.js b/strophe.jinglejs-bundle.js index f9e0704..ac535f8 100644 --- a/strophe.jinglejs-bundle.js +++ b/strophe.jinglejs-bundle.js @@ -1,33016 +1,33016 @@ -/*! - * strophe.jinglejs v0.2.3 - 2017-08-21 - * - * Copyright (c) 2017 Klaus Herberth
- * Released under the MIT license - * - * Please see https://github.com/sualko/strophe.jinglejs/ - * - * @author Klaus Herberth - * @version 0.2.3 - * @license MIT - */ - -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 -} - -function byteLength (b64) { - // base64 is 4/3 + up to two characters of the original data - return b64.length * 3 / 4 - placeHoldersCount(b64) -} - -function toByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - var len = b64.length - placeHolders = placeHoldersCount(b64) - - arr = new Arr(len * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? len - 4 : len - - var L = 0 - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] - arr[L++] = (tmp >> 16) & 0xFF - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - if (placeHolders === 2) { - tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[L++] = tmp & 0xFF - } else if (placeHolders === 1) { - tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[L++] = (tmp >> 8) & 0xFF - arr[L++] = tmp & 0xFF - } - - return arr -} - -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] -} - -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} - -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var output = '' - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 - - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - output += lookup[tmp >> 2] - output += lookup[(tmp << 4) & 0x3F] - output += '==' - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) - output += lookup[tmp >> 10] - output += lookup[(tmp >> 4) & 0x3F] - output += lookup[(tmp << 2) & 0x3F] - output += '=' - } - - parts.push(output) - - return parts.join('') -} - -},{}],4:[function(require,module,exports){ - -},{}],5:[function(require,module,exports){ -(function (global){ -'use strict'; - -var buffer = require('buffer'); -var Buffer = buffer.Buffer; -var SlowBuffer = buffer.SlowBuffer; -var MAX_LEN = buffer.kMaxLength || 2147483647; -exports.alloc = function alloc(size, fill, encoding) { - if (typeof Buffer.alloc === 'function') { - return Buffer.alloc(size, fill, encoding); - } - if (typeof encoding === 'number') { - throw new TypeError('encoding must not be number'); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - var enc = encoding; - var _fill = fill; - if (_fill === undefined) { - enc = undefined; - _fill = 0; - } - var buf = new Buffer(size); - if (typeof _fill === 'string') { - var fillBuf = new Buffer(_fill, enc); - var flen = fillBuf.length; - var i = -1; - while (++i < size) { - buf[i] = fillBuf[i % flen]; - } - } else { - buf.fill(_fill); - } - return buf; -} -exports.allocUnsafe = function allocUnsafe(size) { - if (typeof Buffer.allocUnsafe === 'function') { - return Buffer.allocUnsafe(size); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - return new Buffer(size); -} -exports.from = function from(value, encodingOrOffset, length) { - if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { - return Buffer.from(value, encodingOrOffset, length); - } - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number'); - } - if (typeof value === 'string') { - return new Buffer(value, encodingOrOffset); - } - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - var offset = encodingOrOffset; - if (arguments.length === 1) { - return new Buffer(value); - } - if (typeof offset === 'undefined') { - offset = 0; - } - var len = length; - if (typeof len === 'undefined') { - len = value.byteLength - offset; - } - if (offset >= value.byteLength) { - throw new RangeError('\'offset\' is out of bounds'); - } - if (len > value.byteLength - offset) { - throw new RangeError('\'length\' is out of bounds'); - } - return new Buffer(value.slice(offset, offset + len)); - } - if (Buffer.isBuffer(value)) { - var out = new Buffer(value.length); - value.copy(out, 0, 0, value.length); - return out; - } - if (value) { - if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { - return new Buffer(value); - } - if (value.type === 'Buffer' && Array.isArray(value.data)) { - return new Buffer(value.data); - } - } - - throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); -} -exports.allocUnsafeSlow = function allocUnsafeSlow(size) { - if (typeof Buffer.allocUnsafeSlow === 'function') { - return Buffer.allocUnsafeSlow(size); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size >= MAX_LEN) { - throw new RangeError('size is too large'); - } - return new SlowBuffer(size); -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"buffer":6}],6:[function(require,module,exports){ -(function (global){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ - -'use strict' - -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('isarray') - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Due to various browser bugs, sometimes the Object implementation will be used even - * when the browser supports typed arrays. - * - * Note: - * - * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they - * get the Object implementation, which is slower but behaves correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined - ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() - -/* - * Export kMaxLength after typed array support is determined. - */ -exports.kMaxLength = kMaxLength() - -function typedArraySupport () { - try { - var arr = new Uint8Array(1) - arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} - return arr.foo() === 42 && // typed array instances can be augmented - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -} - -function kMaxLength () { - return Buffer.TYPED_ARRAY_SUPPORT - ? 0x7fffffff - : 0x3fffffff -} - -function createBuffer (that, length) { - if (kMaxLength() < length) { - throw new RangeError('Invalid typed array length') - } - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = new Uint8Array(length) - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - if (that === null) { - that = new Buffer(length) - } - that.length = length - } - - return that -} - -/** - * The Buffer constructor returns instances of `Uint8Array` that have their - * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of - * `Uint8Array`, so the returned instances will have all the node `Buffer` methods - * and the `Uint8Array` methods. Square bracket notation works as expected -- it - * returns a single octet. - * - * The `Uint8Array` prototype remains unmodified. - */ - -function Buffer (arg, encodingOrOffset, length) { - if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { - return new Buffer(arg, encodingOrOffset, length) - } - - // Common case. - if (typeof arg === 'number') { - if (typeof encodingOrOffset === 'string') { - throw new Error( - 'If encoding is specified then the first argument must be a string' - ) - } - return allocUnsafe(this, arg) - } - return from(this, arg, encodingOrOffset, length) -} - -Buffer.poolSize = 8192 // not used by this implementation - -// TODO: Legacy, not needed anymore. Remove in next major version. -Buffer._augment = function (arr) { - arr.__proto__ = Buffer.prototype - return arr -} - -function from (that, value, encodingOrOffset, length) { - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number') - } - - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - return fromArrayBuffer(that, value, encodingOrOffset, length) - } - - if (typeof value === 'string') { - return fromString(that, value, encodingOrOffset) - } - - return fromObject(that, value) -} - -/** - * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError - * if value is a number. - * Buffer.from(str[, encoding]) - * Buffer.from(array) - * Buffer.from(buffer) - * Buffer.from(arrayBuffer[, byteOffset[, length]]) - **/ -Buffer.from = function (value, encodingOrOffset, length) { - return from(null, value, encodingOrOffset, length) -} - -if (Buffer.TYPED_ARRAY_SUPPORT) { - Buffer.prototype.__proto__ = Uint8Array.prototype - Buffer.__proto__ = Uint8Array - if (typeof Symbol !== 'undefined' && Symbol.species && - Buffer[Symbol.species] === Buffer) { - // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 - Object.defineProperty(Buffer, Symbol.species, { - value: null, - configurable: true - }) - } -} - -function assertSize (size) { - if (typeof size !== 'number') { - throw new TypeError('"size" argument must be a number') - } else if (size < 0) { - throw new RangeError('"size" argument must not be negative') - } -} - -function alloc (that, size, fill, encoding) { - assertSize(size) - if (size <= 0) { - return createBuffer(that, size) - } - if (fill !== undefined) { - // Only pay attention to encoding if it's a string. This - // prevents accidentally sending in a number that would - // be interpretted as a start offset. - return typeof encoding === 'string' - ? createBuffer(that, size).fill(fill, encoding) - : createBuffer(that, size).fill(fill) - } - return createBuffer(that, size) -} - -/** - * Creates a new filled Buffer instance. - * alloc(size[, fill[, encoding]]) - **/ -Buffer.alloc = function (size, fill, encoding) { - return alloc(null, size, fill, encoding) -} - -function allocUnsafe (that, size) { - assertSize(size) - that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < size; ++i) { - that[i] = 0 - } - } - return that -} - -/** - * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. - * */ -Buffer.allocUnsafe = function (size) { - return allocUnsafe(null, size) -} -/** - * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. - */ -Buffer.allocUnsafeSlow = function (size) { - return allocUnsafe(null, size) -} - -function fromString (that, string, encoding) { - if (typeof encoding !== 'string' || encoding === '') { - encoding = 'utf8' - } - - if (!Buffer.isEncoding(encoding)) { - throw new TypeError('"encoding" must be a valid string encoding') - } - - var length = byteLength(string, encoding) | 0 - that = createBuffer(that, length) - - var actual = that.write(string, encoding) - - if (actual !== length) { - // Writing a hex string, for example, that contains invalid characters will - // cause everything after the first invalid character to be ignored. (e.g. - // 'abxxcd' will be treated as 'ab') - that = that.slice(0, actual) - } - - return that -} - -function fromArrayLike (that, array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - that = createBuffer(that, length) - for (var i = 0; i < length; i += 1) { - that[i] = array[i] & 255 - } - return that -} - -function fromArrayBuffer (that, array, byteOffset, length) { - array.byteLength // this throws if `array` is not a valid ArrayBuffer - - if (byteOffset < 0 || array.byteLength < byteOffset) { - throw new RangeError('\'offset\' is out of bounds') - } - - if (array.byteLength < byteOffset + (length || 0)) { - throw new RangeError('\'length\' is out of bounds') - } - - if (byteOffset === undefined && length === undefined) { - array = new Uint8Array(array) - } else if (length === undefined) { - array = new Uint8Array(array, byteOffset) - } else { - array = new Uint8Array(array, byteOffset, length) - } - - if (Buffer.TYPED_ARRAY_SUPPORT) { - // Return an augmented `Uint8Array` instance, for best performance - that = array - that.__proto__ = Buffer.prototype - } else { - // Fallback: Return an object instance of the Buffer class - that = fromArrayLike(that, array) - } - return that -} - -function fromObject (that, obj) { - if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - that = createBuffer(that, len) - - if (that.length === 0) { - return that - } - - obj.copy(that, 0, 0, len) - return that - } - - if (obj) { - if ((typeof ArrayBuffer !== 'undefined' && - obj.buffer instanceof ArrayBuffer) || 'length' in obj) { - if (typeof obj.length !== 'number' || isnan(obj.length)) { - return createBuffer(that, 0) - } - return fromArrayLike(that, obj) - } - - if (obj.type === 'Buffer' && isArray(obj.data)) { - return fromArrayLike(that, obj.data) - } - } - - throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') -} - -function checked (length) { - // Note: cannot use `length < kMaxLength()` here because that fails when - // length is NaN (which is otherwise coerced to zero.) - if (length >= kMaxLength()) { - throw new RangeError('Attempt to allocate Buffer larger than maximum ' + - 'size: 0x' + kMaxLength().toString(16) + ' bytes') - } - return length | 0 -} - -function SlowBuffer (length) { - if (+length != length) { // eslint-disable-line eqeqeq - length = 0 - } - return Buffer.alloc(+length) -} - -Buffer.isBuffer = function isBuffer (b) { - return !!(b != null && b._isBuffer) -} - -Buffer.compare = function compare (a, b) { - if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { - throw new TypeError('Arguments must be Buffers') - } - - if (a === b) return 0 - - var x = a.length - var y = b.length - - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i] - y = b[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -Buffer.isEncoding = function isEncoding (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'latin1': - case 'binary': - case 'base64': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.concat = function concat (list, length) { - if (!isArray(list)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - - if (list.length === 0) { - return Buffer.alloc(0) - } - - var i - if (length === undefined) { - length = 0 - for (i = 0; i < list.length; ++i) { - length += list[i].length - } - } - - var buffer = Buffer.allocUnsafe(length) - var pos = 0 - for (i = 0; i < list.length; ++i) { - var buf = list[i] - if (!Buffer.isBuffer(buf)) { - throw new TypeError('"list" argument must be an Array of Buffers') - } - buf.copy(buffer, pos) - pos += buf.length - } - return buffer -} - -function byteLength (string, encoding) { - if (Buffer.isBuffer(string)) { - return string.length - } - if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && - (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { - return string.byteLength - } - if (typeof string !== 'string') { - string = '' + string - } - - var len = string.length - if (len === 0) return 0 - - // Use a for loop to avoid recursion - var loweredCase = false - for (;;) { - switch (encoding) { - case 'ascii': - case 'latin1': - case 'binary': - return len - case 'utf8': - case 'utf-8': - case undefined: - return utf8ToBytes(string).length - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return len * 2 - case 'hex': - return len >>> 1 - case 'base64': - return base64ToBytes(string).length - default: - if (loweredCase) return utf8ToBytes(string).length // assume utf8 - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} -Buffer.byteLength = byteLength - -function slowToString (encoding, start, end) { - var loweredCase = false - - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only - // property of a typed array. - - // This behaves neither like String nor Uint8Array in that we set start/end - // to their upper/lower bounds if the value passed is out of range. - // undefined is handled specially as per ECMA-262 6th Edition, - // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. - if (start === undefined || start < 0) { - start = 0 - } - // Return early if start > this.length. Done here to prevent potential uint32 - // coercion fail below. - if (start > this.length) { - return '' - } - - if (end === undefined || end > this.length) { - end = this.length - } - - if (end <= 0) { - return '' - } - - // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 - - if (end <= start) { - return '' - } - - if (!encoding) encoding = 'utf8' - - while (true) { - switch (encoding) { - case 'hex': - return hexSlice(this, start, end) - - case 'utf8': - case 'utf-8': - return utf8Slice(this, start, end) - - case 'ascii': - return asciiSlice(this, start, end) - - case 'latin1': - case 'binary': - return latin1Slice(this, start, end) - - case 'base64': - return base64Slice(this, start, end) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return utf16leSlice(this, start, end) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() - loweredCase = true - } - } -} - -// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect -// Buffer instances. -Buffer.prototype._isBuffer = true - -function swap (b, n, m) { - var i = b[n] - b[n] = b[m] - b[m] = i -} - -Buffer.prototype.swap16 = function swap16 () { - var len = this.length - if (len % 2 !== 0) { - throw new RangeError('Buffer size must be a multiple of 16-bits') - } - for (var i = 0; i < len; i += 2) { - swap(this, i, i + 1) - } - return this -} - -Buffer.prototype.swap32 = function swap32 () { - var len = this.length - if (len % 4 !== 0) { - throw new RangeError('Buffer size must be a multiple of 32-bits') - } - for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) - swap(this, i + 1, i + 2) - } - return this -} - -Buffer.prototype.swap64 = function swap64 () { - var len = this.length - if (len % 8 !== 0) { - throw new RangeError('Buffer size must be a multiple of 64-bits') - } - for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) - swap(this, i + 3, i + 4) - } - return this -} - -Buffer.prototype.toString = function toString () { - var length = this.length | 0 - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) - return slowToString.apply(this, arguments) -} - -Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true - return Buffer.compare(this, b) === 0 -} - -Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES - if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') - if (this.length > max) str += ' ... ' - } - return '' -} - -Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { - if (!Buffer.isBuffer(target)) { - throw new TypeError('Argument must be a Buffer') - } - - if (start === undefined) { - start = 0 - } - if (end === undefined) { - end = target ? target.length : 0 - } - if (thisStart === undefined) { - thisStart = 0 - } - if (thisEnd === undefined) { - thisEnd = this.length - } - - if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { - throw new RangeError('out of range index') - } - - if (thisStart >= thisEnd && start >= end) { - return 0 - } - if (thisStart >= thisEnd) { - return -1 - } - if (start >= end) { - return 1 - } - - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 - - if (this === target) return 0 - - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) - - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) - - for (var i = 0; i < len; ++i) { - if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] - break - } - } - - if (x < y) return -1 - if (y < x) return 1 - return 0 -} - -// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, -// OR the last index of `val` in `buffer` at offset <= `byteOffset`. -// -// Arguments: -// - buffer - a Buffer to search -// - val - a string, Buffer, or number -// - byteOffset - an index into `buffer`; will be clamped to an int32 -// - encoding - an optional encoding, relevant is val is a string -// - dir - true for indexOf, false for lastIndexOf -function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { - // Empty buffer means no match - if (buffer.length === 0) return -1 - - // Normalize byteOffset - if (typeof byteOffset === 'string') { - encoding = byteOffset - byteOffset = 0 - } else if (byteOffset > 0x7fffffff) { - byteOffset = 0x7fffffff - } else if (byteOffset < -0x80000000) { - byteOffset = -0x80000000 - } - byteOffset = +byteOffset // Coerce to Number. - if (isNaN(byteOffset)) { - // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer - byteOffset = dir ? 0 : (buffer.length - 1) - } - - // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset - if (byteOffset >= buffer.length) { - if (dir) return -1 - else byteOffset = buffer.length - 1 - } else if (byteOffset < 0) { - if (dir) byteOffset = 0 - else return -1 - } - - // Normalize val - if (typeof val === 'string') { - val = Buffer.from(val, encoding) - } - - // Finally, search either indexOf (if dir is true) or lastIndexOf - if (Buffer.isBuffer(val)) { - // Special case: looking for empty string/buffer always fails - if (val.length === 0) { - return -1 - } - return arrayIndexOf(buffer, val, byteOffset, encoding, dir) - } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] - if (Buffer.TYPED_ARRAY_SUPPORT && - typeof Uint8Array.prototype.indexOf === 'function') { - if (dir) { - return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) - } else { - return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) - } - } - return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) - } - - throw new TypeError('val must be string, number or Buffer') -} - -function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length - - if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() - if (encoding === 'ucs2' || encoding === 'ucs-2' || - encoding === 'utf16le' || encoding === 'utf-16le') { - if (arr.length < 2 || val.length < 2) { - return -1 - } - indexSize = 2 - arrLength /= 2 - valLength /= 2 - byteOffset /= 2 - } - } - - function read (buf, i) { - if (indexSize === 1) { - return buf[i] - } else { - return buf.readUInt16BE(i * indexSize) - } - } - - var i - if (dir) { - var foundIndex = -1 - for (i = byteOffset; i < arrLength; i++) { - if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i - if (i - foundIndex + 1 === valLength) return foundIndex * indexSize - } else { - if (foundIndex !== -1) i -= i - foundIndex - foundIndex = -1 - } - } - } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength - for (i = byteOffset; i >= 0; i--) { - var found = true - for (var j = 0; j < valLength; j++) { - if (read(arr, i + j) !== read(val, j)) { - found = false - break - } - } - if (found) return i - } - } - - return -1 -} - -Buffer.prototype.includes = function includes (val, byteOffset, encoding) { - return this.indexOf(val, byteOffset, encoding) !== -1 -} - -Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} - -Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { - return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} - -function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - - // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(parsed)) return i - buf[offset + i] = parsed - } - return i -} - -function utf8Write (buf, string, offset, length) { - return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) -} - -function asciiWrite (buf, string, offset, length) { - return blitBuffer(asciiToBytes(string), buf, offset, length) -} - -function latin1Write (buf, string, offset, length) { - return asciiWrite(buf, string, offset, length) -} - -function base64Write (buf, string, offset, length) { - return blitBuffer(base64ToBytes(string), buf, offset, length) -} - -function ucs2Write (buf, string, offset, length) { - return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) -} - -Buffer.prototype.write = function write (string, offset, length, encoding) { - // Buffer#write(string) - if (offset === undefined) { - encoding = 'utf8' - length = this.length - offset = 0 - // Buffer#write(string, encoding) - } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length - offset = 0 - // Buffer#write(string, offset[, length][, encoding]) - } else if (isFinite(offset)) { - offset = offset | 0 - if (isFinite(length)) { - length = length | 0 - if (encoding === undefined) encoding = 'utf8' - } else { - encoding = length - length = undefined - } - // legacy write(string, encoding, offset, length) - remove in v0.13 - } else { - throw new Error( - 'Buffer.write(string, encoding, offset[, length]) is no longer supported' - ) - } - - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining - - if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { - throw new RangeError('Attempt to write outside buffer bounds') - } - - if (!encoding) encoding = 'utf8' - - var loweredCase = false - for (;;) { - switch (encoding) { - case 'hex': - return hexWrite(this, string, offset, length) - - case 'utf8': - case 'utf-8': - return utf8Write(this, string, offset, length) - - case 'ascii': - return asciiWrite(this, string, offset, length) - - case 'latin1': - case 'binary': - return latin1Write(this, string, offset, length) - - case 'base64': - // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) - - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return ucs2Write(this, string, offset, length) - - default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() - loweredCase = true - } - } -} - -Buffer.prototype.toJSON = function toJSON () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -function base64Slice (buf, start, end) { - if (start === 0 && end === buf.length) { - return base64.fromByteArray(buf) - } else { - return base64.fromByteArray(buf.slice(start, end)) - } -} - -function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] - - var i = start - while (i < end) { - var firstByte = buf[i] - var codePoint = null - var bytesPerSequence = (firstByte > 0xEF) ? 4 - : (firstByte > 0xDF) ? 3 - : (firstByte > 0xBF) ? 2 - : 1 - - if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint - - switch (bytesPerSequence) { - case 1: - if (firstByte < 0x80) { - codePoint = firstByte - } - break - case 2: - secondByte = buf[i + 1] - if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) - if (tempCodePoint > 0x7F) { - codePoint = tempCodePoint - } - } - break - case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) - if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { - codePoint = tempCodePoint - } - } - break - case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] - if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) - if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { - codePoint = tempCodePoint - } - } - } - } - - if (codePoint === null) { - // we did not generate a valid codePoint so insert a - // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD - bytesPerSequence = 1 - } else if (codePoint > 0xFFFF) { - // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) - codePoint = 0xDC00 | codePoint & 0x3FF - } - - res.push(codePoint) - i += bytesPerSequence - } - - return decodeCodePointsArray(res) -} - -// Based on http://stackoverflow.com/a/22747272/680742, the browser with -// the lowest limit is Chrome, with 0x10000 args. -// We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 - -function decodeCodePointsArray (codePoints) { - var len = codePoints.length - if (len <= MAX_ARGUMENTS_LENGTH) { - return String.fromCharCode.apply(String, codePoints) // avoid extra slice() - } - - // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 - while (i < len) { - res += String.fromCharCode.apply( - String, - codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) - ) - } - return res -} - -function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i] & 0x7F) - } - return ret -} - -function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; ++i) { - ret += String.fromCharCode(buf[i]) - } - return ret -} - -function hexSlice (buf, start, end) { - var len = buf.length - - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len - - var out = '' - for (var i = start; i < end; ++i) { - out += toHex(buf[i]) - } - return out -} - -function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' - for (var i = 0; i < bytes.length; i += 2) { - res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) - } - return res -} - -Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end - - if (start < 0) { - start += len - if (start < 0) start = 0 - } else if (start > len) { - start = len - } - - if (end < 0) { - end += len - if (end < 0) end = 0 - } else if (end > len) { - end = len - } - - if (end < start) end = start - - var newBuf - if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = this.subarray(start, end) - newBuf.__proto__ = Buffer.prototype - } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined) - for (var i = 0; i < sliceLen; ++i) { - newBuf[i] = this[i + start] - } - } - - return newBuf -} - -/* - * Need to make sure that buffer isn't trying to write out of bounds. - */ -function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') - if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') -} - -Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - - return val -} - -Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - checkOffset(offset, byteLength, this.length) - } - - var val = this[offset + --byteLength] - var mul = 1 - while (byteLength > 0 && (mul *= 0x100)) { - val += this[offset + --byteLength] * mul - } - - return val -} - -Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - return this[offset] -} - -Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return this[offset] | (this[offset + 1] << 8) -} - -Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - return (this[offset] << 8) | this[offset + 1] -} - -Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return ((this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16)) + - (this[offset + 3] * 0x1000000) -} - -Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] * 0x1000000) + - ((this[offset + 1] << 16) | - (this[offset + 2] << 8) | - this[offset + 3]) -} - -Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var val = this[offset] - var mul = 1 - var i = 0 - while (++i < byteLength && (mul *= 0x100)) { - val += this[offset + i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) - - var i = byteLength - var mul = 1 - var val = this[offset + --i] - while (i > 0 && (mul *= 0x100)) { - val += this[offset + --i] * mul - } - mul *= 0x80 - - if (val >= mul) val -= Math.pow(2, 8 * byteLength) - - return val -} - -Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) - return ((0xff - this[offset] + 1) * -1) -} - -Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) - return (val & 0x8000) ? val | 0xFFFF0000 : val -} - -Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset]) | - (this[offset + 1] << 8) | - (this[offset + 2] << 16) | - (this[offset + 3] << 24) -} - -Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - - return (this[offset] << 24) | - (this[offset + 1] << 16) | - (this[offset + 2] << 8) | - (this[offset + 3]) -} - -Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, true, 23, 4) -} - -Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) - return ieee754.read(this, offset, false, 23, 4) -} - -Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, true, 52, 8) -} - -Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) - return ieee754.read(this, offset, false, 52, 8) -} - -function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') - if (offset + ext > buf.length) throw new RangeError('Index out of range') -} - -Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var mul = 1 - var i = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 - checkInt(this, value, offset, byteLength, maxBytes, 0) - } - - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - this[offset + i] = (value / mul) & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = (value & 0xff) - return offset + 1 -} - -function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { - buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - -Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } - return offset + 2 -} - -Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } - return offset + 2 -} - -function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 - for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { - buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - -Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) - this[offset] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} - -Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} - -Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF - while (++i < byteLength && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) - - checkInt(this, value, offset, byteLength, limit - 1, -limit) - } - - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF - while (--i >= 0 && (mul *= 0x100)) { - if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { - sub = 1 - } - this[offset + i] = ((value / mul) >> 0) - sub & 0xFF - } - - return offset + byteLength -} - -Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) - return offset + 1 -} - -Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - } else { - objectWriteUInt16(this, value, offset, true) - } - return offset + 2 -} - -Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) - this[offset + 1] = (value & 0xff) - } else { - objectWriteUInt16(this, value, offset, false) - } - return offset + 2 -} - -Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) - this[offset + 3] = (value >>> 24) - } else { - objectWriteUInt32(this, value, offset, true) - } - return offset + 4 -} - -Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 - if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) - this[offset + 3] = (value & 0xff) - } else { - objectWriteUInt32(this, value, offset, false) - } - return offset + 4 -} - -function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') - if (offset < 0) throw new RangeError('Index out of range') -} - -function writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - ieee754.write(buf, value, offset, littleEndian, 23, 4) - return offset + 4 -} - -Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { - return writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { - return writeFloat(this, value, offset, false, noAssert) -} - -function writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - ieee754.write(buf, value, offset, littleEndian, 52, 8) - return offset + 8 -} - -Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { - return writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { - return writeDouble(this, value, offset, false, noAssert) -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start - - // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 - - // Fatal error conditions - if (targetStart < 0) { - throw new RangeError('targetStart out of bounds') - } - if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) end = this.length - if (target.length - targetStart < end - start) { - end = target.length - targetStart + start - } - - var len = end - start - var i - - if (this === target && start < targetStart && targetStart < end) { - // descending copy from end - for (i = len - 1; i >= 0; --i) { - target[i + targetStart] = this[i + start] - } - } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { - // ascending copy from start - for (i = 0; i < len; ++i) { - target[i + targetStart] = this[i + start] - } - } else { - Uint8Array.prototype.set.call( - target, - this.subarray(start, start + len), - targetStart - ) - } - - return len -} - -// Usage: -// buffer.fill(number[, offset[, end]]) -// buffer.fill(buffer[, offset[, end]]) -// buffer.fill(string[, offset[, end]][, encoding]) -Buffer.prototype.fill = function fill (val, start, end, encoding) { - // Handle string cases: - if (typeof val === 'string') { - if (typeof start === 'string') { - encoding = start - start = 0 - end = this.length - } else if (typeof end === 'string') { - encoding = end - end = this.length - } - if (val.length === 1) { - var code = val.charCodeAt(0) - if (code < 256) { - val = code - } - } - if (encoding !== undefined && typeof encoding !== 'string') { - throw new TypeError('encoding must be a string') - } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { - throw new TypeError('Unknown encoding: ' + encoding) - } - } else if (typeof val === 'number') { - val = val & 255 - } - - // Invalid ranges are not set to a default, so can range check early. - if (start < 0 || this.length < start || this.length < end) { - throw new RangeError('Out of range index') - } - - if (end <= start) { - return this - } - - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 - - if (!val) val = 0 - - var i - if (typeof val === 'number') { - for (i = start; i < end; ++i) { - this[i] = val - } - } else { - var bytes = Buffer.isBuffer(val) - ? val - : utf8ToBytes(new Buffer(val, encoding).toString()) - var len = bytes.length - for (i = 0; i < end - start; ++i) { - this[i + start] = bytes[i % len] - } - } - - return this -} - -// HELPER FUNCTIONS -// ================ - -var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g - -function base64clean (str) { - // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') - // Node converts strings with length < 2 to '' - if (str.length < 2) return '' - // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not - while (str.length % 4 !== 0) { - str = str + '=' - } - return str -} - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] - - for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) - - // is surrogate component - if (codePoint > 0xD7FF && codePoint < 0xE000) { - // last char was a lead - if (!leadSurrogate) { - // no lead yet - if (codePoint > 0xDBFF) { - // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } else if (i + 1 === length) { - // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - continue - } - - // valid lead - leadSurrogate = codePoint - - continue - } - - // 2 leads in a row - if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint - continue - } - - // valid surrogate pair - codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 - } else if (leadSurrogate) { - // valid bmp char, but last char was a lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - } - - leadSurrogate = null - - // encode utf8 - if (codePoint < 0x80) { - if ((units -= 1) < 0) break - bytes.push(codePoint) - } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break - bytes.push( - codePoint >> 0x6 | 0xC0, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break - bytes.push( - codePoint >> 0xC | 0xE0, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break - bytes.push( - codePoint >> 0x12 | 0xF0, - codePoint >> 0xC & 0x3F | 0x80, - codePoint >> 0x6 & 0x3F | 0x80, - codePoint & 0x3F | 0x80 - ) - } else { - throw new Error('Invalid code point') - } - } - - return bytes -} - -function asciiToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - // Node's code seems to be doing this and not & 0x7F.. - byteArray.push(str.charCodeAt(i) & 0xFF) - } - return byteArray -} - -function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break - - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(base64clean(str)) -} - -function blitBuffer (src, dst, offset, length) { - for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break - dst[i + offset] = src[i] - } - return i -} - -function isnan (val) { - return val !== val // eslint-disable-line no-self-compare -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":3,"ieee754":44,"isarray":48}],7:[function(require,module,exports){ -(function (Buffer){ -var Transform = require('stream').Transform -var inherits = require('inherits') -var StringDecoder = require('string_decoder').StringDecoder -module.exports = CipherBase -inherits(CipherBase, Transform) -function CipherBase (hashMode) { - Transform.call(this) - this.hashMode = typeof hashMode === 'string' - if (this.hashMode) { - this[hashMode] = this._finalOrDigest - } else { - this.final = this._finalOrDigest - } - this._decoder = null - this._encoding = null -} -CipherBase.prototype.update = function (data, inputEnc, outputEnc) { - if (typeof data === 'string') { - data = new Buffer(data, inputEnc) - } - var outData = this._update(data) - if (this.hashMode) { - return this - } - if (outputEnc) { - outData = this._toString(outData, outputEnc) - } - return outData -} - -CipherBase.prototype.setAutoPadding = function () {} - -CipherBase.prototype.getAuthTag = function () { - throw new Error('trying to get auth tag in unsupported state') -} - -CipherBase.prototype.setAuthTag = function () { - throw new Error('trying to set auth tag in unsupported state') -} - -CipherBase.prototype.setAAD = function () { - throw new Error('trying to set aad in unsupported state') -} - -CipherBase.prototype._transform = function (data, _, next) { - var err - try { - if (this.hashMode) { - this._update(data) - } else { - this.push(this._update(data)) - } - } catch (e) { - err = e - } finally { - next(err) - } -} -CipherBase.prototype._flush = function (done) { - var err - try { - this.push(this._final()) - } catch (e) { - err = e - } finally { - done(err) - } -} -CipherBase.prototype._finalOrDigest = function (outputEnc) { - var outData = this._final() || new Buffer('') - if (outputEnc) { - outData = this._toString(outData, outputEnc, true) - } - return outData -} - -CipherBase.prototype._toString = function (value, enc, fin) { - if (!this._decoder) { - this._decoder = new StringDecoder(enc) - this._encoding = enc - } - if (this._encoding !== enc) { - throw new Error('can\'t switch encodings') - } - var out = this._decoder.write(value) - if (fin) { - out += this._decoder.end() - } - return out -} - -}).call(this,require("buffer").Buffer) -},{"buffer":6,"inherits":45,"stream":193,"string_decoder":194}],8:[function(require,module,exports){ -require('../../modules/es6.object.assign'); -module.exports = require('../../modules/$.core').Object.assign; -},{"../../modules/$.core":11,"../../modules/es6.object.assign":21}],9:[function(require,module,exports){ -module.exports = function(it){ - if(typeof it != 'function')throw TypeError(it + ' is not a function!'); - return it; -}; -},{}],10:[function(require,module,exports){ -var toString = {}.toString; - -module.exports = function(it){ - return toString.call(it).slice(8, -1); -}; -},{}],11:[function(require,module,exports){ -var core = module.exports = {version: '1.2.6'}; -if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef -},{}],12:[function(require,module,exports){ -// optional / simple context binding -var aFunction = require('./$.a-function'); -module.exports = function(fn, that, length){ - aFunction(fn); - if(that === undefined)return fn; - switch(length){ - case 1: return function(a){ - return fn.call(that, a); - }; - case 2: return function(a, b){ - return fn.call(that, a, b); - }; - case 3: return function(a, b, c){ - return fn.call(that, a, b, c); - }; - } - return function(/* ...args */){ - return fn.apply(that, arguments); - }; -}; -},{"./$.a-function":9}],13:[function(require,module,exports){ -// 7.2.1 RequireObjectCoercible(argument) -module.exports = function(it){ - if(it == undefined)throw TypeError("Can't call method on " + it); - return it; -}; -},{}],14:[function(require,module,exports){ -var global = require('./$.global') - , core = require('./$.core') - , ctx = require('./$.ctx') - , PROTOTYPE = 'prototype'; - -var $export = function(type, name, source){ - var IS_FORCED = type & $export.F - , IS_GLOBAL = type & $export.G - , IS_STATIC = type & $export.S - , IS_PROTO = type & $export.P - , IS_BIND = type & $export.B - , IS_WRAP = type & $export.W - , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) - , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] - , key, own, out; - if(IS_GLOBAL)source = name; - for(key in source){ - // contains in native - own = !IS_FORCED && target && key in target; - if(own && key in exports)continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function(C){ - var F = function(param){ - return this instanceof C ? new C(param) : C(param); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out; - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -module.exports = $export; -},{"./$.core":11,"./$.ctx":12,"./$.global":16}],15:[function(require,module,exports){ -module.exports = function(exec){ - try { - return !!exec(); - } catch(e){ - return true; - } -}; -},{}],16:[function(require,module,exports){ -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); -if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef -},{}],17:[function(require,module,exports){ -// fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = require('./$.cof'); -module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ - return cof(it) == 'String' ? it.split('') : Object(it); -}; -},{"./$.cof":10}],18:[function(require,module,exports){ -var $Object = Object; -module.exports = { - create: $Object.create, - getProto: $Object.getPrototypeOf, - isEnum: {}.propertyIsEnumerable, - getDesc: $Object.getOwnPropertyDescriptor, - setDesc: $Object.defineProperty, - setDescs: $Object.defineProperties, - getKeys: $Object.keys, - getNames: $Object.getOwnPropertyNames, - getSymbols: $Object.getOwnPropertySymbols, - each: [].forEach -}; -},{}],19:[function(require,module,exports){ -// 19.1.2.1 Object.assign(target, source, ...) -var $ = require('./$') - , toObject = require('./$.to-object') - , IObject = require('./$.iobject'); - -// should work with symbols and should have deterministic property order (V8 bug) -module.exports = require('./$.fails')(function(){ - var a = Object.assign - , A = {} - , B = {} - , S = Symbol() - , K = 'abcdefghijklmnopqrst'; - A[S] = 7; - K.split('').forEach(function(k){ B[k] = k; }); - return a({}, A)[S] != 7 || Object.keys(a({}, B)).join('') != K; -}) ? function assign(target, source){ // eslint-disable-line no-unused-vars - var T = toObject(target) - , $$ = arguments - , $$len = $$.length - , index = 1 - , getKeys = $.getKeys - , getSymbols = $.getSymbols - , isEnum = $.isEnum; - while($$len > index){ - var S = IObject($$[index++]) - , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) - , length = keys.length - , j = 0 - , key; - while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; - } - return T; -} : Object.assign; -},{"./$":18,"./$.fails":15,"./$.iobject":17,"./$.to-object":20}],20:[function(require,module,exports){ -// 7.1.13 ToObject(argument) -var defined = require('./$.defined'); -module.exports = function(it){ - return Object(defined(it)); -}; -},{"./$.defined":13}],21:[function(require,module,exports){ -// 19.1.3.1 Object.assign(target, source) -var $export = require('./$.export'); - -$export($export.S + $export.F, 'Object', {assign: require('./$.object-assign')}); -},{"./$.export":14,"./$.object-assign":19}],22:[function(require,module,exports){ -(function (Buffer){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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. - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. - -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); - } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = Buffer.isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - -}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) -},{"../../is-buffer/index.js":47}],23:[function(require,module,exports){ -(function (Buffer){ -'use strict'; -var inherits = require('inherits') -var md5 = require('./md5') -var rmd160 = require('ripemd160') -var sha = require('sha.js') - -var Base = require('cipher-base') - -function HashNoConstructor(hash) { - Base.call(this, 'digest') - - this._hash = hash - this.buffers = [] -} - -inherits(HashNoConstructor, Base) - -HashNoConstructor.prototype._update = function (data) { - this.buffers.push(data) -} - -HashNoConstructor.prototype._final = function () { - var buf = Buffer.concat(this.buffers) - var r = this._hash(buf) - this.buffers = null - - return r -} - -function Hash(hash) { - Base.call(this, 'digest') - - this._hash = hash -} - -inherits(Hash, Base) - -Hash.prototype._update = function (data) { - this._hash.update(data) -} - -Hash.prototype._final = function () { - return this._hash.digest() -} - -module.exports = function createHash (alg) { - alg = alg.toLowerCase() - if ('md5' === alg) return new HashNoConstructor(md5) - if ('rmd160' === alg || 'ripemd160' === alg) return new HashNoConstructor(rmd160) - - return new Hash(sha(alg)) -} - -}).call(this,require("buffer").Buffer) -},{"./md5":25,"buffer":6,"cipher-base":7,"inherits":45,"ripemd160":168,"sha.js":186}],24:[function(require,module,exports){ -(function (Buffer){ -'use strict'; -var intSize = 4; -var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0); -var chrsz = 8; - -function toArray(buf, bigEndian) { - if ((buf.length % intSize) !== 0) { - var len = buf.length + (intSize - (buf.length % intSize)); - buf = Buffer.concat([buf, zeroBuffer], len); - } - - var arr = []; - var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE; - for (var i = 0; i < buf.length; i += intSize) { - arr.push(fn.call(buf, i)); - } - return arr; -} - -function toBuffer(arr, size, bigEndian) { - var buf = new Buffer(size); - var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE; - for (var i = 0; i < arr.length; i++) { - fn.call(buf, arr[i], i * 4, true); - } - return buf; -} - -function hash(buf, fn, hashSize, bigEndian) { - if (!Buffer.isBuffer(buf)) buf = new Buffer(buf); - var arr = fn(toArray(buf, bigEndian), buf.length * chrsz); - return toBuffer(arr, hashSize, bigEndian); -} -exports.hash = hash; -}).call(this,require("buffer").Buffer) -},{"buffer":6}],25:[function(require,module,exports){ -'use strict'; -/* - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message - * Digest Algorithm, as defined in RFC 1321. - * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for more info. - */ - -var helpers = require('./helpers'); - -/* - * Calculate the MD5 of an array of little-endian words, and a bit length - */ -function core_md5(x, len) -{ - /* append padding */ - x[len >> 5] |= 0x80 << ((len) % 32); - x[(((len + 64) >>> 9) << 4) + 14] = len; - - var a = 1732584193; - var b = -271733879; - var c = -1732584194; - var d = 271733878; - - for(var i = 0; i < x.length; i += 16) - { - var olda = a; - var oldb = b; - var oldc = c; - var oldd = d; - - a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); - d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); - c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); - b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); - a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); - d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); - c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); - b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); - a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); - d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); - c = md5_ff(c, d, a, b, x[i+10], 17, -42063); - b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); - a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); - d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); - c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); - b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); - - a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); - d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); - c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); - b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); - a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); - d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); - c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); - b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); - a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); - d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); - c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); - b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); - a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); - d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); - c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); - b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); - - a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); - d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); - c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); - b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); - a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); - d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); - c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); - b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); - a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); - d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); - c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); - b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); - a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); - d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); - c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); - b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); - - a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); - d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); - c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); - b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); - a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); - d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); - c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); - b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); - a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); - d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); - c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); - b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); - a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); - d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); - c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); - b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); - - a = safe_add(a, olda); - b = safe_add(b, oldb); - c = safe_add(c, oldc); - d = safe_add(d, oldd); - } - return Array(a, b, c, d); - -} - -/* - * These functions implement the four basic operations the algorithm uses. - */ -function md5_cmn(q, a, b, x, s, t) -{ - return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); -} -function md5_ff(a, b, c, d, x, s, t) -{ - return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); -} -function md5_gg(a, b, c, d, x, s, t) -{ - return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); -} -function md5_hh(a, b, c, d, x, s, t) -{ - return md5_cmn(b ^ c ^ d, a, b, x, s, t); -} -function md5_ii(a, b, c, d, x, s, t) -{ - return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); -} - -/* - * Add integers, wrapping at 2^32. This uses 16-bit operations internally - * to work around bugs in some JS interpreters. - */ -function safe_add(x, y) -{ - var lsw = (x & 0xFFFF) + (y & 0xFFFF); - var msw = (x >> 16) + (y >> 16) + (lsw >> 16); - return (msw << 16) | (lsw & 0xFFFF); -} - -/* - * Bitwise rotate a 32-bit number to the left. - */ -function bit_rol(num, cnt) -{ - return (num << cnt) | (num >>> (32 - cnt)); -} - -module.exports = function md5(buf) { - return helpers.hash(buf, core_md5, 16); -}; -},{"./helpers":24}],26:[function(require,module,exports){ -(function (Buffer){ -'use strict'; -var createHash = require('create-hash/browser'); -var inherits = require('inherits') - -var Transform = require('stream').Transform - -var ZEROS = new Buffer(128) -ZEROS.fill(0) - -function Hmac(alg, key) { - Transform.call(this) - alg = alg.toLowerCase() - if (typeof key === 'string') { - key = new Buffer(key) - } - - var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 - - this._alg = alg - this._key = key - - if (key.length > blocksize) { - key = createHash(alg).update(key).digest() - - } else if (key.length < blocksize) { - key = Buffer.concat([key, ZEROS], blocksize) - } - - var ipad = this._ipad = new Buffer(blocksize) - var opad = this._opad = new Buffer(blocksize) - - for (var i = 0; i < blocksize; i++) { - ipad[i] = key[i] ^ 0x36 - opad[i] = key[i] ^ 0x5C - } - - this._hash = createHash(alg).update(ipad) -} - -inherits(Hmac, Transform) - -Hmac.prototype.update = function (data, enc) { - this._hash.update(data, enc) - - return this -} - -Hmac.prototype._transform = function (data, _, next) { - this._hash.update(data) - - next() -} - -Hmac.prototype._flush = function (next) { - this.push(this.digest()) - - next() -} - -Hmac.prototype.digest = function (enc) { - var h = this._hash.digest() - - return createHash(this._alg).update(this._opad).update(h).digest(enc) -} - -module.exports = function createHmac(alg, key) { - return new Hmac(alg, key) -} - -}).call(this,require("buffer").Buffer) -},{"buffer":6,"create-hash/browser":23,"inherits":45,"stream":193}],27:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// 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. - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - // At least give some kind of context to the user - var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); - err.context = er; - throw err; - } - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - args = Array.prototype.slice.call(arguments, 1); - handler.apply(this, args); - } - } else if (isObject(handler)) { - args = Array.prototype.slice.call(arguments, 1); - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; - - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; - } - return 0; -}; - -EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],28:[function(require,module,exports){ -var arr = []; -var each = arr.forEach; -var slice = arr.slice; - - -module.exports = function(obj) { - each.call(slice.call(arguments, 1), function(source) { - if (source) { - for (var prop in source) { - obj[prop] = source[prop]; - } - } - }); - return obj; -}; - -},{}],29:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); -var util = require('util'); - -function Sender(opts) { - WildEmitter.call(this); - var options = opts || {}; - this.config = { - chunksize: 16384, - pacing: 0 - }; - // set our config from options - var item; - for (item in options) { - this.config[item] = options[item]; - } - - this.file = null; - this.channel = null; -} -util.inherits(Sender, WildEmitter); - -Sender.prototype.send = function (file, channel) { - var self = this; - this.file = file; - this.channel = channel; - var usePoll = typeof channel.bufferedAmountLowThreshold !== 'number'; - var offset = 0; - var sliceFile = function() { - var reader = new window.FileReader(); - reader.onload = (function() { - return function(e) { - self.channel.send(e.target.result); - self.emit('progress', offset, file.size, e.target.result); - - if (file.size > offset + e.target.result.byteLength) { - if (usePoll) { - window.setTimeout(sliceFile, self.config.pacing); - } else if (channel.bufferedAmount <= channel.bufferedAmountLowThreshold) { - window.setTimeout(sliceFile, 0); - } else { - // wait for bufferedAmountLow to fire - } - } else { - self.emit('progress', file.size, file.size, null); - self.emit('sentFile'); - } - offset = offset + self.config.chunksize; - }; - })(file); - var slice = file.slice(offset, offset + self.config.chunksize); - reader.readAsArrayBuffer(slice); - }; - if (!usePoll) { - channel.bufferedAmountLowThreshold = 8 * this.config.chunksize; - channel.addEventListener('bufferedamountlow', sliceFile); - } - window.setTimeout(sliceFile, 0); -}; - -function Receiver() { - WildEmitter.call(this); - - this.receiveBuffer = []; - this.received = 0; - this.metadata = {}; - this.channel = null; -} -util.inherits(Receiver, WildEmitter); - -Receiver.prototype.receive = function (metadata, channel) { - var self = this; - - if (metadata) { - this.metadata = metadata; - } - this.channel = channel; - // chrome only supports arraybuffers and those make it easier to calc the hash - channel.binaryType = 'arraybuffer'; - this.channel.onmessage = function (event) { - var len = event.data.byteLength; - self.received += len; - self.receiveBuffer.push(event.data); - - self.emit('progress', self.received, self.metadata.size, event.data); - if (self.received === self.metadata.size) { - self.emit('receivedFile', new window.Blob(self.receiveBuffer), self.metadata); - self.receiveBuffer = []; // discard receivebuffer - } else if (self.received > self.metadata.size) { - // FIXME - console.error('received more than expected, discarding...'); - self.receiveBuffer = []; // just discard... - - } - }; -}; - -module.exports = {}; -module.exports.support = typeof window !== 'undefined' && window && window.File && window.FileReader && window.Blob; -module.exports.Sender = Sender; -module.exports.Receiver = Receiver; - -},{"util":208,"wildemitter":223}],30:[function(require,module,exports){ -var WildEmitter = require('wildemitter'); -var util = require('util'); -var hashes = require('iana-hashes'); -var base = require('./filetransfer'); - -// drop-in replacement for filetransfer which also calculates hashes -function Sender(opts) { - WildEmitter.call(this); - var self = this; - this.base = new base.Sender(opts); - - var options = opts || {}; - if (!options.hash) { - options.hash = 'sha-1'; - } - this.hash = hashes.createHash(options.hash); - - this.base.on('progress', function (start, size, data) { - self.emit('progress', start, size, data); - if (data) { - self.hash.update(new Uint8Array(data)); - } - }); - this.base.on('sentFile', function () { - self.emit('sentFile', {hash: self.hash.digest('hex'), algo: options.hash }); - }); -} -util.inherits(Sender, WildEmitter); -Sender.prototype.send = function () { - this.base.send.apply(this.base, arguments); -}; - -function Receiver(opts) { - WildEmitter.call(this); - var self = this; - this.base = new base.Receiver(opts); - - var options = opts || {}; - if (!options.hash) { - options.hash = 'sha-1'; - } - this.hash = hashes.createHash(options.hash); - - this.base.on('progress', function (start, size, data) { - self.emit('progress', start, size, data); - if (data) { - self.hash.update(new Uint8Array(data)); - } - }); - this.base.on('receivedFile', function (file, metadata) { - metadata.actualhash = self.hash.digest('hex'); - self.emit('receivedFile', file, metadata); - }); -} -util.inherits(Receiver, WildEmitter); -Receiver.prototype.receive = function () { - this.base.receive.apply(this.base, arguments); -}; -Object.defineProperty(Receiver.prototype, 'metadata', { - get: function () { - return this.base.metadata; - }, - set: function (value) { - this.base.metadata = value; - } -}); - -module.exports = {}; -module.exports.support = base.support; -module.exports.Sender = Sender; -module.exports.Receiver = Receiver; - -},{"./filetransfer":29,"iana-hashes":42,"util":208,"wildemitter":223}],31:[function(require,module,exports){ -// cache for constraints and callback -var cache = {}; - -module.exports = function (constraints, cb) { - var hasConstraints = arguments.length === 2; - var callback = hasConstraints ? cb : constraints; - var error; - - if (typeof window === 'undefined' || window.location.protocol === 'http:') { - error = new Error('NavigatorUserMediaError'); - error.name = 'HTTPS_REQUIRED'; - return callback(error); - } - - if (window.navigator.userAgent.match('Chrome')) { - var chromever = parseInt(window.navigator.userAgent.match(/Chrome\/(.*) /)[1], 10); - var maxver = 33; - var isCef = !window.chrome.webstore; - // "known" crash in chrome 34 and 35 on linux - if (window.navigator.userAgent.match('Linux')) maxver = 35; - - // check that the extension is installed by looking for a - // sessionStorage variable that contains the extension id - // this has to be set after installation unless the contest - // script does that - if (sessionStorage.getScreenMediaJSExtensionId) { - chrome.runtime.sendMessage(sessionStorage.getScreenMediaJSExtensionId, - {type:'getScreen', id: 1}, null, - function (data) { - if (!data || data.sourceId === '') { // user canceled - var error = new Error('NavigatorUserMediaError'); - error.name = 'NotAllowedError'; - callback(error); - } else { - constraints = (hasConstraints && constraints) || {audio: false, video: { - mandatory: { - chromeMediaSource: 'desktop', - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3 - } - }}; - constraints.video.mandatory.chromeMediaSourceId = data.sourceId; - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - callback(null, stream); - }).catch(function (err) { - callback(err); - }); - } - } - ); - } else if (window.cefGetScreenMedia) { - //window.cefGetScreenMedia is experimental - may be removed without notice - window.cefGetScreenMedia(function(sourceId) { - if (!sourceId) { - var error = new Error('cefGetScreenMediaError'); - error.name = 'CEF_GETSCREENMEDIA_CANCELED'; - callback(error); - } else { - constraints = (hasConstraints && constraints) || {audio: false, video: { - mandatory: { - chromeMediaSource: 'desktop', - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3 - }, - optional: [ - {googLeakyBucket: true}, - {googTemporalLayeredScreencast: true} - ] - }}; - constraints.video.mandatory.chromeMediaSourceId = sourceId; - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - callback(null, stream); - }).catch(function (err) { - callback(err); - }); - } - }); - } else if (isCef || (chromever >= 26 && chromever <= maxver)) { - // chrome 26 - chrome 33 way to do it -- requires bad chrome://flags - // note: this is basically in maintenance mode and will go away soon - constraints = (hasConstraints && constraints) || { - video: { - mandatory: { - googLeakyBucket: true, - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3, - chromeMediaSource: 'screen' - } - } - }; - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - callback(null, stream); - }).catch(function (err) { - callback(err); - }); - } else { - // chrome 34+ way requiring an extension - var pending = window.setTimeout(function () { - error = new Error('NavigatorUserMediaError'); - error.name = 'EXTENSION_UNAVAILABLE'; - return callback(error); - }, 1000); - cache[pending] = [callback, hasConstraints ? constraints : null]; - window.postMessage({ type: 'getScreen', id: pending }, '*'); - } - } else if (window.navigator.userAgent.match('Firefox')) { - var ffver = parseInt(window.navigator.userAgent.match(/Firefox\/(.*)/)[1], 10); - if (ffver >= 33) { - constraints = (hasConstraints && constraints) || { - video: { - mozMediaSource: 'window', - mediaSource: 'window' - } - }; - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - callback(null, stream); - var lastTime = stream.currentTime; - var polly = window.setInterval(function () { - if (!stream) window.clearInterval(polly); - if (stream.currentTime == lastTime) { - window.clearInterval(polly); - if (stream.onended) { - stream.onended(); - } - } - lastTime = stream.currentTime; - }, 500); - }).catch(function (err) { - callback(err); - }); - } else { - error = new Error('NavigatorUserMediaError'); - error.name = 'EXTENSION_UNAVAILABLE'; // does not make much sense but... - } - } -}; - -typeof window !== 'undefined' && window.addEventListener('message', function (event) { - if (event.origin != window.location.origin) { - return; - } - if (event.data.type == 'gotScreen' && cache[event.data.id]) { - var data = cache[event.data.id]; - var constraints = data[1]; - var callback = data[0]; - delete cache[event.data.id]; - - if (event.data.sourceId === '') { // user canceled - var error = new Error('NavigatorUserMediaError'); - error.name = 'NotAllowedError'; - callback(error); - } else { - constraints = constraints || {audio: false, video: { - mandatory: { - chromeMediaSource: 'desktop', - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3 - }, - optional: [ - {googLeakyBucket: true}, - {googTemporalLayeredScreencast: true} - ] - }}; - constraints.video.mandatory.chromeMediaSourceId = event.data.sourceId; - window.navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { - callback(null, stream); - }).catch(function (err) { - callback(err); - }); - } - } else if (event.data.type == 'getScreenPending') { - window.clearTimeout(event.data.id); - } -}); - -},{}],32:[function(require,module,exports){ -// getUserMedia helper by @HenrikJoreteg used for navigator.getUserMedia shim -var adapter = require('webrtc-adapter'); - -module.exports = function (constraints, cb) { - var error; - var haveOpts = arguments.length === 2; - var defaultOpts = {video: true, audio: true}; - - var denied = 'PermissionDeniedError'; - var altDenied = 'PERMISSION_DENIED'; - var notSatisfied = 'ConstraintNotSatisfiedError'; - - // make constraints optional - if (!haveOpts) { - cb = constraints; - constraints = defaultOpts; - } - - // treat lack of browser support like an error - if (typeof navigator === 'undefined' || !navigator.getUserMedia) { - // throw proper error per spec - error = new Error('MediaStreamError'); - error.name = 'NotSupportedError'; - - // keep all callbacks async - return setTimeout(function () { - cb(error); - }, 0); - } - - // normalize error handling when no media types are requested - if (!constraints.audio && !constraints.video) { - error = new Error('MediaStreamError'); - error.name = 'NoMediaRequestedError'; - - // keep all callbacks async - return setTimeout(function () { - cb(error); - }, 0); - } - - navigator.mediaDevices.getUserMedia(constraints) - .then(function (stream) { - cb(null, stream); - }).catch(function (err) { - var error; - // coerce into an error object since FF gives us a string - // there are only two valid names according to the spec - // we coerce all non-denied to "constraint not satisfied". - if (typeof err === 'string') { - error = new Error('MediaStreamError'); - if (err === denied || err === altDenied) { - error.name = denied; - } else { - error.name = notSatisfied; - } - } else { - // if we get an error object make sure '.name' property is set - // according to spec: http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermediaerror-and-navigatorusermediaerrorcallback - error = err; - if (!error.name) { - // this is likely chrome which - // sets a property called "ERROR_DENIED" on the error object - // if so we make sure to set a name - if (error[denied]) { - err.name = denied; - } else { - err.name = notSatisfied; - } - } - } - - cb(error); - }); -}; - -},{"webrtc-adapter":33}],33:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ - -'use strict'; - -// Shimming starts here. -(function() { - // Utils. - var logging = require('./utils').log; - var browserDetails = require('./utils').browserDetails; - // Export to the adapter global object visible in the browser. - module.exports.browserDetails = browserDetails; - module.exports.extractVersion = require('./utils').extractVersion; - module.exports.disableLog = require('./utils').disableLog; - - // Uncomment the line below if you want logging to occur, including logging - // for the switch statement below. Can also be turned on in the browser via - // adapter.disableLog(false), but then logging from the switch statement below - // will not appear. - // require('./utils').disableLog(false); - - // Browser shims. - var chromeShim = require('./chrome/chrome_shim') || null; - var edgeShim = require('./edge/edge_shim') || null; - var firefoxShim = require('./firefox/firefox_shim') || null; - var safariShim = require('./safari/safari_shim') || null; - - // Shim browser if found. - switch (browserDetails.browser) { - case 'opera': // fallthrough as it uses chrome shims - case 'chrome': - if (!chromeShim || !chromeShim.shimPeerConnection) { - logging('Chrome shim is not included in this adapter release.'); - return; - } - logging('adapter.js shimming chrome.'); - // Export to the adapter global object visible in the browser. - module.exports.browserShim = chromeShim; - - chromeShim.shimGetUserMedia(); - chromeShim.shimMediaStream(); - chromeShim.shimSourceObject(); - chromeShim.shimPeerConnection(); - chromeShim.shimOnTrack(); - break; - case 'firefox': - if (!firefoxShim || !firefoxShim.shimPeerConnection) { - logging('Firefox shim is not included in this adapter release.'); - return; - } - logging('adapter.js shimming firefox.'); - // Export to the adapter global object visible in the browser. - module.exports.browserShim = firefoxShim; - - firefoxShim.shimGetUserMedia(); - firefoxShim.shimSourceObject(); - firefoxShim.shimPeerConnection(); - firefoxShim.shimOnTrack(); - break; - case 'edge': - if (!edgeShim || !edgeShim.shimPeerConnection) { - logging('MS edge shim is not included in this adapter release.'); - return; - } - logging('adapter.js shimming edge.'); - // Export to the adapter global object visible in the browser. - module.exports.browserShim = edgeShim; - - edgeShim.shimGetUserMedia(); - edgeShim.shimPeerConnection(); - break; - case 'safari': - if (!safariShim) { - logging('Safari shim is not included in this adapter release.'); - return; - } - logging('adapter.js shimming safari.'); - // Export to the adapter global object visible in the browser. - module.exports.browserShim = safariShim; - - safariShim.shimGetUserMedia(); - break; - default: - logging('Unsupported browser!'); - } -})(); - -},{"./chrome/chrome_shim":34,"./edge/edge_shim":36,"./firefox/firefox_shim":38,"./safari/safari_shim":40,"./utils":41}],34:[function(require,module,exports){ - -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; -var logging = require('../utils.js').log; -var browserDetails = require('../utils.js').browserDetails; - -var chromeShim = { - shimMediaStream: function() { - window.MediaStream = window.MediaStream || window.webkitMediaStream; - }, - - shimOnTrack: function() { - if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in - window.RTCPeerConnection.prototype)) { - Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { - get: function() { - return this._ontrack; - }, - set: function(f) { - var self = this; - if (this._ontrack) { - this.removeEventListener('track', this._ontrack); - this.removeEventListener('addstream', this._ontrackpoly); - } - this.addEventListener('track', this._ontrack = f); - this.addEventListener('addstream', this._ontrackpoly = function(e) { - // onaddstream does not fire when a track is added to an existing - // stream. But stream.onaddtrack is implemented so we use that. - e.stream.addEventListener('addtrack', function(te) { - var event = new Event('track'); - event.track = te.track; - event.receiver = {track: te.track}; - event.streams = [e.stream]; - self.dispatchEvent(event); - }); - e.stream.getTracks().forEach(function(track) { - var event = new Event('track'); - event.track = track; - event.receiver = {track: track}; - event.streams = [e.stream]; - this.dispatchEvent(event); - }.bind(this)); - }.bind(this)); - } - }); - } - }, - - shimSourceObject: function() { - if (typeof window === 'object') { - if (window.HTMLMediaElement && - !('srcObject' in window.HTMLMediaElement.prototype)) { - // Shim the srcObject property, once, when HTMLMediaElement is found. - Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { - get: function() { - return this._srcObject; - }, - set: function(stream) { - var self = this; - // Use _srcObject as a private property for this shim - this._srcObject = stream; - if (this.src) { - URL.revokeObjectURL(this.src); - } - - if (!stream) { - this.src = ''; - return; - } - this.src = URL.createObjectURL(stream); - // We need to recreate the blob url when a track is added or - // removed. Doing it manually since we want to avoid a recursion. - stream.addEventListener('addtrack', function() { - if (self.src) { - URL.revokeObjectURL(self.src); - } - self.src = URL.createObjectURL(stream); - }); - stream.addEventListener('removetrack', function() { - if (self.src) { - URL.revokeObjectURL(self.src); - } - self.src = URL.createObjectURL(stream); - }); - } - }); - } - } - }, - - shimPeerConnection: function() { - // The RTCPeerConnection object. - window.RTCPeerConnection = function(pcConfig, pcConstraints) { - // Translate iceTransportPolicy to iceTransports, - // see https://code.google.com/p/webrtc/issues/detail?id=4869 - logging('PeerConnection'); - if (pcConfig && pcConfig.iceTransportPolicy) { - pcConfig.iceTransports = pcConfig.iceTransportPolicy; - } - - var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); - var origGetStats = pc.getStats.bind(pc); - pc.getStats = function(selector, successCallback, errorCallback) { - var self = this; - var args = arguments; - - // If selector is a function then we are in the old style stats so just - // pass back the original getStats format to avoid breaking old users. - if (arguments.length > 0 && typeof selector === 'function') { - return origGetStats(selector, successCallback); - } - - var fixChromeStats_ = function(response) { - var standardReport = {}; - var reports = response.result(); - reports.forEach(function(report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: report.type - }; - report.names().forEach(function(name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - - return standardReport; - }; - - // shim getStats with maplike support - var makeMapStats = function(stats, legacyStats) { - var map = new Map(Object.keys(stats).map(function(key) { - return[key, stats[key]]; - })); - legacyStats = legacyStats || stats; - Object.keys(legacyStats).forEach(function(key) { - map[key] = legacyStats[key]; - }); - return map; - }; - - if (arguments.length >= 2) { - var successCallbackWrapper_ = function(response) { - args[1](makeMapStats(fixChromeStats_(response))); - }; - - return origGetStats.apply(this, [successCallbackWrapper_, - arguments[0]]); - } - - // promise-support - return new Promise(function(resolve, reject) { - if (args.length === 1 && typeof selector === 'object') { - origGetStats.apply(self, [ - function(response) { - resolve(makeMapStats(fixChromeStats_(response))); - }, reject]); - } else { - // Preserve legacy chrome stats only on legacy access of stats obj - origGetStats.apply(self, [ - function(response) { - resolve(makeMapStats(fixChromeStats_(response), - response.result())); - }, reject]); - } - }).then(successCallback, errorCallback); - }; - - return pc; - }; - window.RTCPeerConnection.prototype = webkitRTCPeerConnection.prototype; - - // wrap static methods. Currently just generateCertificate. - if (webkitRTCPeerConnection.generateCertificate) { - Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { - get: function() { - return webkitRTCPeerConnection.generateCertificate; - } - }); - } - - ['createOffer', 'createAnswer'].forEach(function(method) { - var nativeMethod = webkitRTCPeerConnection.prototype[method]; - webkitRTCPeerConnection.prototype[method] = function() { - var self = this; - if (arguments.length < 1 || (arguments.length === 1 && - typeof arguments[0] === 'object')) { - var opts = arguments.length === 1 ? arguments[0] : undefined; - return new Promise(function(resolve, reject) { - nativeMethod.apply(self, [resolve, reject, opts]); - }); - } - return nativeMethod.apply(this, arguments); - }; - }); - - // add promise support -- natively available in Chrome 51 - if (browserDetails.version < 51) { - ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] - .forEach(function(method) { - var nativeMethod = webkitRTCPeerConnection.prototype[method]; - webkitRTCPeerConnection.prototype[method] = function() { - var args = arguments; - var self = this; - var promise = new Promise(function(resolve, reject) { - nativeMethod.apply(self, [args[0], resolve, reject]); - }); - if (args.length < 2) { - return promise; - } - return promise.then(function() { - args[1].apply(null, []); - }, - function(err) { - if (args.length >= 3) { - args[2].apply(null, [err]); - } - }); - }; - }); - } - - // shim implicit creation of RTCSessionDescription/RTCIceCandidate - ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] - .forEach(function(method) { - var nativeMethod = webkitRTCPeerConnection.prototype[method]; - webkitRTCPeerConnection.prototype[method] = function() { - arguments[0] = new ((method === 'addIceCandidate') ? - RTCIceCandidate : RTCSessionDescription)(arguments[0]); - return nativeMethod.apply(this, arguments); - }; - }); - - // support for addIceCandidate(null or undefined) - var nativeAddIceCandidate = - RTCPeerConnection.prototype.addIceCandidate; - RTCPeerConnection.prototype.addIceCandidate = function() { - if (!arguments[0]) { - if (arguments[1]) { - arguments[1].apply(null); - } - return Promise.resolve(); - } - return nativeAddIceCandidate.apply(this, arguments); - }; - } -}; - - -// Expose public methods. -module.exports = { - shimMediaStream: chromeShim.shimMediaStream, - shimOnTrack: chromeShim.shimOnTrack, - shimSourceObject: chromeShim.shimSourceObject, - shimPeerConnection: chromeShim.shimPeerConnection, - shimGetUserMedia: require('./getusermedia') -}; - -},{"../utils.js":41,"./getusermedia":35}],35:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; -var logging = require('../utils.js').log; - -// Expose public methods. -module.exports = function() { - var constraintsToChrome_ = function(c) { - if (typeof c !== 'object' || c.mandatory || c.optional) { - return c; - } - var cc = {}; - Object.keys(c).forEach(function(key) { - if (key === 'require' || key === 'advanced' || key === 'mediaSource') { - return; - } - var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]}; - if (r.exact !== undefined && typeof r.exact === 'number') { - r.min = r.max = r.exact; - } - var oldname_ = function(prefix, name) { - if (prefix) { - return prefix + name.charAt(0).toUpperCase() + name.slice(1); - } - return (name === 'deviceId') ? 'sourceId' : name; - }; - if (r.ideal !== undefined) { - cc.optional = cc.optional || []; - var oc = {}; - if (typeof r.ideal === 'number') { - oc[oldname_('min', key)] = r.ideal; - cc.optional.push(oc); - oc = {}; - oc[oldname_('max', key)] = r.ideal; - cc.optional.push(oc); - } else { - oc[oldname_('', key)] = r.ideal; - cc.optional.push(oc); - } - } - if (r.exact !== undefined && typeof r.exact !== 'number') { - cc.mandatory = cc.mandatory || {}; - cc.mandatory[oldname_('', key)] = r.exact; - } else { - ['min', 'max'].forEach(function(mix) { - if (r[mix] !== undefined) { - cc.mandatory = cc.mandatory || {}; - cc.mandatory[oldname_(mix, key)] = r[mix]; - } - }); - } - }); - if (c.advanced) { - cc.optional = (cc.optional || []).concat(c.advanced); - } - return cc; - }; - - var shimConstraints_ = function(constraints, func) { - constraints = JSON.parse(JSON.stringify(constraints)); - if (constraints && constraints.audio) { - constraints.audio = constraintsToChrome_(constraints.audio); - } - if (constraints && typeof constraints.video === 'object') { - // Shim facingMode for mobile, where it defaults to "user". - var face = constraints.video.facingMode; - face = face && ((typeof face === 'object') ? face : {ideal: face}); - - if ((face && (face.exact === 'user' || face.exact === 'environment' || - face.ideal === 'user' || face.ideal === 'environment')) && - !(navigator.mediaDevices.getSupportedConstraints && - navigator.mediaDevices.getSupportedConstraints().facingMode)) { - delete constraints.video.facingMode; - if (face.exact === 'environment' || face.ideal === 'environment') { - // Look for "back" in label, or use last cam (typically back cam). - return navigator.mediaDevices.enumerateDevices() - .then(function(devices) { - devices = devices.filter(function(d) { - return d.kind === 'videoinput'; - }); - var back = devices.find(function(d) { - return d.label.toLowerCase().indexOf('back') !== -1; - }) || (devices.length && devices[devices.length - 1]); - if (back) { - constraints.video.deviceId = face.exact ? {exact: back.deviceId} : - {ideal: back.deviceId}; - } - constraints.video = constraintsToChrome_(constraints.video); - logging('chrome: ' + JSON.stringify(constraints)); - return func(constraints); - }); - } - } - constraints.video = constraintsToChrome_(constraints.video); - } - logging('chrome: ' + JSON.stringify(constraints)); - return func(constraints); - }; - - var shimError_ = function(e) { - return { - name: { - PermissionDeniedError: 'NotAllowedError', - ConstraintNotSatisfiedError: 'OverconstrainedError' - }[e.name] || e.name, - message: e.message, - constraint: e.constraintName, - toString: function() { - return this.name + (this.message && ': ') + this.message; - } - }; - }; - - var getUserMedia_ = function(constraints, onSuccess, onError) { - shimConstraints_(constraints, function(c) { - navigator.webkitGetUserMedia(c, onSuccess, function(e) { - onError(shimError_(e)); - }); - }); - }; - - navigator.getUserMedia = getUserMedia_; - - // Returns the result of getUserMedia as a Promise. - var getUserMediaPromise_ = function(constraints) { - return new Promise(function(resolve, reject) { - navigator.getUserMedia(constraints, resolve, reject); - }); - }; - - if (!navigator.mediaDevices) { - navigator.mediaDevices = { - getUserMedia: getUserMediaPromise_, - enumerateDevices: function() { - return new Promise(function(resolve) { - var kinds = {audio: 'audioinput', video: 'videoinput'}; - return MediaStreamTrack.getSources(function(devices) { - resolve(devices.map(function(device) { - return {label: device.label, - kind: kinds[device.kind], - deviceId: device.id, - groupId: ''}; - })); - }); - }); - } - }; - } - - // A shim for getUserMedia method on the mediaDevices object. - // TODO(KaptenJansson) remove once implemented in Chrome stable. - if (!navigator.mediaDevices.getUserMedia) { - navigator.mediaDevices.getUserMedia = function(constraints) { - return getUserMediaPromise_(constraints); - }; - } else { - // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia - // function which returns a Promise, it does not accept spec-style - // constraints. - var origGetUserMedia = navigator.mediaDevices.getUserMedia. - bind(navigator.mediaDevices); - navigator.mediaDevices.getUserMedia = function(cs) { - return shimConstraints_(cs, function(c) { - return origGetUserMedia(c).then(function(stream) { - if (c.audio && !stream.getAudioTracks().length || - c.video && !stream.getVideoTracks().length) { - stream.getTracks().forEach(function(track) { - track.stop(); - }); - throw new DOMException('', 'NotFoundError'); - } - return stream; - }, function(e) { - return Promise.reject(shimError_(e)); - }); - }); - }; - } - - // Dummy devicechange event methods. - // TODO(KaptenJansson) remove once implemented in Chrome stable. - if (typeof navigator.mediaDevices.addEventListener === 'undefined') { - navigator.mediaDevices.addEventListener = function() { - logging('Dummy mediaDevices.addEventListener called.'); - }; - } - if (typeof navigator.mediaDevices.removeEventListener === 'undefined') { - navigator.mediaDevices.removeEventListener = function() { - logging('Dummy mediaDevices.removeEventListener called.'); - }; - } -}; - -},{"../utils.js":41}],36:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; - -var SDPUtils = require('sdp'); -var browserDetails = require('../utils').browserDetails; - -var edgeShim = { - shimPeerConnection: function() { - if (window.RTCIceGatherer) { - // ORTC defines an RTCIceCandidate object but no constructor. - // Not implemented in Edge. - if (!window.RTCIceCandidate) { - window.RTCIceCandidate = function(args) { - return args; - }; - } - // ORTC does not have a session description object but - // other browsers (i.e. Chrome) that will support both PC and ORTC - // in the future might have this defined already. - if (!window.RTCSessionDescription) { - window.RTCSessionDescription = function(args) { - return args; - }; - } - // this adds an additional event listener to MediaStrackTrack that signals - // when a tracks enabled property was changed. - var origMSTEnabled = Object.getOwnPropertyDescriptor( - MediaStreamTrack.prototype, 'enabled'); - Object.defineProperty(MediaStreamTrack.prototype, 'enabled', { - set: function(value) { - origMSTEnabled.set.call(this, value); - var ev = new Event('enabled'); - ev.enabled = value; - this.dispatchEvent(ev); - } - }); - } - - window.RTCPeerConnection = function(config) { - var self = this; - - var _eventTarget = document.createDocumentFragment(); - ['addEventListener', 'removeEventListener', 'dispatchEvent'] - .forEach(function(method) { - self[method] = _eventTarget[method].bind(_eventTarget); - }); - - this.onicecandidate = null; - this.onaddstream = null; - this.ontrack = null; - this.onremovestream = null; - this.onsignalingstatechange = null; - this.oniceconnectionstatechange = null; - this.onnegotiationneeded = null; - this.ondatachannel = null; - - this.localStreams = []; - this.remoteStreams = []; - this.getLocalStreams = function() { - return self.localStreams; - }; - this.getRemoteStreams = function() { - return self.remoteStreams; - }; - - this.localDescription = new RTCSessionDescription({ - type: '', - sdp: '' - }); - this.remoteDescription = new RTCSessionDescription({ - type: '', - sdp: '' - }); - this.signalingState = 'stable'; - this.iceConnectionState = 'new'; - this.iceGatheringState = 'new'; - - this.iceOptions = { - gatherPolicy: 'all', - iceServers: [] - }; - if (config && config.iceTransportPolicy) { - switch (config.iceTransportPolicy) { - case 'all': - case 'relay': - this.iceOptions.gatherPolicy = config.iceTransportPolicy; - break; - case 'none': - // FIXME: remove once implementation and spec have added this. - throw new TypeError('iceTransportPolicy "none" not supported'); - default: - // don't set iceTransportPolicy. - break; - } - } - this.usingBundle = config && config.bundlePolicy === 'max-bundle'; - - if (config && config.iceServers) { - // Edge does not like - // 1) stun: - // 2) turn: that does not have all of turn:host:port?transport=udp - // 3) turn: with ipv6 addresses - var iceServers = JSON.parse(JSON.stringify(config.iceServers)); - this.iceOptions.iceServers = iceServers.filter(function(server) { - if (server && server.urls) { - var urls = server.urls; - if (typeof urls === 'string') { - urls = [urls]; - } - urls = urls.filter(function(url) { - return (url.indexOf('turn:') === 0 && - url.indexOf('transport=udp') !== -1 && - url.indexOf('turn:[') === -1) || - (url.indexOf('stun:') === 0 && - browserDetails.version >= 14393); - })[0]; - return !!urls; - } - return false; - }); - } - this._config = config; - - // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ... - // everything that is needed to describe a SDP m-line. - this.transceivers = []; - - // since the iceGatherer is currently created in createOffer but we - // must not emit candidates until after setLocalDescription we buffer - // them in this array. - this._localIceCandidatesBuffer = []; - }; - - window.RTCPeerConnection.prototype._emitBufferedCandidates = function() { - var self = this; - var sections = SDPUtils.splitSections(self.localDescription.sdp); - // FIXME: need to apply ice candidates in a way which is async but - // in-order - this._localIceCandidatesBuffer.forEach(function(event) { - var end = !event.candidate || Object.keys(event.candidate).length === 0; - if (end) { - for (var j = 1; j < sections.length; j++) { - if (sections[j].indexOf('\r\na=end-of-candidates\r\n') === -1) { - sections[j] += 'a=end-of-candidates\r\n'; - } - } - } else if (event.candidate.candidate.indexOf('typ endOfCandidates') - === -1) { - sections[event.candidate.sdpMLineIndex + 1] += - 'a=' + event.candidate.candidate + '\r\n'; - } - self.localDescription.sdp = sections.join(''); - self.dispatchEvent(event); - if (self.onicecandidate !== null) { - self.onicecandidate(event); - } - if (!event.candidate && self.iceGatheringState !== 'complete') { - var complete = self.transceivers.every(function(transceiver) { - return transceiver.iceGatherer && - transceiver.iceGatherer.state === 'completed'; - }); - if (complete) { - self.iceGatheringState = 'complete'; - } - } - }); - this._localIceCandidatesBuffer = []; - }; - - window.RTCPeerConnection.prototype.getConfiguration = function() { - return this._config; - }; - - window.RTCPeerConnection.prototype.addStream = function(stream) { - // Clone is necessary for local demos mostly, attaching directly - // to two different senders does not work (build 10547). - var clonedStream = stream.clone(); - stream.getTracks().forEach(function(track, idx) { - var clonedTrack = clonedStream.getTracks()[idx]; - track.addEventListener('enabled', function(event) { - clonedTrack.enabled = event.enabled; - }); - }); - this.localStreams.push(clonedStream); - this._maybeFireNegotiationNeeded(); - }; - - window.RTCPeerConnection.prototype.removeStream = function(stream) { - var idx = this.localStreams.indexOf(stream); - if (idx > -1) { - this.localStreams.splice(idx, 1); - this._maybeFireNegotiationNeeded(); - } - }; - - window.RTCPeerConnection.prototype.getSenders = function() { - return this.transceivers.filter(function(transceiver) { - return !!transceiver.rtpSender; - }) - .map(function(transceiver) { - return transceiver.rtpSender; - }); - }; - - window.RTCPeerConnection.prototype.getReceivers = function() { - return this.transceivers.filter(function(transceiver) { - return !!transceiver.rtpReceiver; - }) - .map(function(transceiver) { - return transceiver.rtpReceiver; - }); - }; - - // Determines the intersection of local and remote capabilities. - window.RTCPeerConnection.prototype._getCommonCapabilities = - function(localCapabilities, remoteCapabilities) { - var commonCapabilities = { - codecs: [], - headerExtensions: [], - fecMechanisms: [] - }; - localCapabilities.codecs.forEach(function(lCodec) { - for (var i = 0; i < remoteCapabilities.codecs.length; i++) { - var rCodec = remoteCapabilities.codecs[i]; - if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() && - lCodec.clockRate === rCodec.clockRate) { - // number of channels is the highest common number of channels - rCodec.numChannels = Math.min(lCodec.numChannels, - rCodec.numChannels); - // push rCodec so we reply with offerer payload type - commonCapabilities.codecs.push(rCodec); - - // determine common feedback mechanisms - rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) { - for (var j = 0; j < lCodec.rtcpFeedback.length; j++) { - if (lCodec.rtcpFeedback[j].type === fb.type && - lCodec.rtcpFeedback[j].parameter === fb.parameter) { - return true; - } - } - return false; - }); - // FIXME: also need to determine .parameters - // see https://github.com/openpeer/ortc/issues/569 - break; - } - } - }); - - localCapabilities.headerExtensions - .forEach(function(lHeaderExtension) { - for (var i = 0; i < remoteCapabilities.headerExtensions.length; - i++) { - var rHeaderExtension = remoteCapabilities.headerExtensions[i]; - if (lHeaderExtension.uri === rHeaderExtension.uri) { - commonCapabilities.headerExtensions.push(rHeaderExtension); - break; - } - } - }); - - // FIXME: fecMechanisms - return commonCapabilities; - }; - - // Create ICE gatherer, ICE transport and DTLS transport. - window.RTCPeerConnection.prototype._createIceAndDtlsTransports = - function(mid, sdpMLineIndex) { - var self = this; - var iceGatherer = new RTCIceGatherer(self.iceOptions); - var iceTransport = new RTCIceTransport(iceGatherer); - iceGatherer.onlocalcandidate = function(evt) { - var event = new Event('icecandidate'); - event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex}; - - var cand = evt.candidate; - var end = !cand || Object.keys(cand).length === 0; - // Edge emits an empty object for RTCIceCandidateComplete‥ - if (end) { - // polyfill since RTCIceGatherer.state is not implemented in - // Edge 10547 yet. - if (iceGatherer.state === undefined) { - iceGatherer.state = 'completed'; - } - - // Emit a candidate with type endOfCandidates to make the samples - // work. Edge requires addIceCandidate with this empty candidate - // to start checking. The real solution is to signal - // end-of-candidates to the other side when getting the null - // candidate but some apps (like the samples) don't do that. - event.candidate.candidate = - 'candidate:1 1 udp 1 0.0.0.0 9 typ endOfCandidates'; - } else { - // RTCIceCandidate doesn't have a component, needs to be added - cand.component = iceTransport.component === 'RTCP' ? 2 : 1; - event.candidate.candidate = SDPUtils.writeCandidate(cand); - } - - // update local description. - var sections = SDPUtils.splitSections(self.localDescription.sdp); - if (event.candidate.candidate.indexOf('typ endOfCandidates') - === -1) { - sections[event.candidate.sdpMLineIndex + 1] += - 'a=' + event.candidate.candidate + '\r\n'; - } else { - sections[event.candidate.sdpMLineIndex + 1] += - 'a=end-of-candidates\r\n'; - } - self.localDescription.sdp = sections.join(''); - - var complete = self.transceivers.every(function(transceiver) { - return transceiver.iceGatherer && - transceiver.iceGatherer.state === 'completed'; - }); - - // Emit candidate if localDescription is set. - // Also emits null candidate when all gatherers are complete. - switch (self.iceGatheringState) { - case 'new': - self._localIceCandidatesBuffer.push(event); - if (end && complete) { - self._localIceCandidatesBuffer.push( - new Event('icecandidate')); - } - break; - case 'gathering': - self._emitBufferedCandidates(); - self.dispatchEvent(event); - if (self.onicecandidate !== null) { - self.onicecandidate(event); - } - if (complete) { - self.dispatchEvent(new Event('icecandidate')); - if (self.onicecandidate !== null) { - self.onicecandidate(new Event('icecandidate')); - } - self.iceGatheringState = 'complete'; - } - break; - case 'complete': - // should not happen... currently! - break; - default: // no-op. - break; - } - }; - iceTransport.onicestatechange = function() { - self._updateConnectionState(); - }; - - var dtlsTransport = new RTCDtlsTransport(iceTransport); - dtlsTransport.ondtlsstatechange = function() { - self._updateConnectionState(); - }; - dtlsTransport.onerror = function() { - // onerror does not set state to failed by itself. - dtlsTransport.state = 'failed'; - self._updateConnectionState(); - }; - - return { - iceGatherer: iceGatherer, - iceTransport: iceTransport, - dtlsTransport: dtlsTransport - }; - }; - - // Start the RTP Sender and Receiver for a transceiver. - window.RTCPeerConnection.prototype._transceive = function(transceiver, - send, recv) { - var params = this._getCommonCapabilities(transceiver.localCapabilities, - transceiver.remoteCapabilities); - if (send && transceiver.rtpSender) { - params.encodings = transceiver.sendEncodingParameters; - params.rtcp = { - cname: SDPUtils.localCName - }; - if (transceiver.recvEncodingParameters.length) { - params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc; - } - transceiver.rtpSender.send(params); - } - if (recv && transceiver.rtpReceiver) { - // remove RTX field in Edge 14942 - if (transceiver.kind === 'video' - && transceiver.recvEncodingParameters) { - transceiver.recvEncodingParameters.forEach(function(p) { - delete p.rtx; - }); - } - params.encodings = transceiver.recvEncodingParameters; - params.rtcp = { - cname: transceiver.cname - }; - if (transceiver.sendEncodingParameters.length) { - params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc; - } - transceiver.rtpReceiver.receive(params); - } - }; - - window.RTCPeerConnection.prototype.setLocalDescription = - function(description) { - var self = this; - var sections; - var sessionpart; - if (description.type === 'offer') { - // FIXME: What was the purpose of this empty if statement? - // if (!this._pendingOffer) { - // } else { - if (this._pendingOffer) { - // VERY limited support for SDP munging. Limited to: - // * changing the order of codecs - sections = SDPUtils.splitSections(description.sdp); - sessionpart = sections.shift(); - sections.forEach(function(mediaSection, sdpMLineIndex) { - var caps = SDPUtils.parseRtpParameters(mediaSection); - self._pendingOffer[sdpMLineIndex].localCapabilities = caps; - }); - this.transceivers = this._pendingOffer; - delete this._pendingOffer; - } - } else if (description.type === 'answer') { - sections = SDPUtils.splitSections(self.remoteDescription.sdp); - sessionpart = sections.shift(); - var isIceLite = SDPUtils.matchPrefix(sessionpart, - 'a=ice-lite').length > 0; - sections.forEach(function(mediaSection, sdpMLineIndex) { - var transceiver = self.transceivers[sdpMLineIndex]; - var iceGatherer = transceiver.iceGatherer; - var iceTransport = transceiver.iceTransport; - var dtlsTransport = transceiver.dtlsTransport; - var localCapabilities = transceiver.localCapabilities; - var remoteCapabilities = transceiver.remoteCapabilities; - - var rejected = mediaSection.split('\n', 1)[0] - .split(' ', 2)[1] === '0'; - - if (!rejected && !transceiver.isDatachannel) { - var remoteIceParameters = SDPUtils.getIceParameters( - mediaSection, sessionpart); - if (isIceLite) { - var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:') - .map(function(cand) { - return SDPUtils.parseCandidate(cand); - }) - .filter(function(cand) { - return cand.component === '1'; - }); - // ice-lite only includes host candidates in the SDP so we can - // use setRemoteCandidates (which implies an - // RTCIceCandidateComplete) - if (cands.length) { - iceTransport.setRemoteCandidates(cands); - } - } - var remoteDtlsParameters = SDPUtils.getDtlsParameters( - mediaSection, sessionpart); - if (isIceLite) { - remoteDtlsParameters.role = 'server'; - } - - if (!self.usingBundle || sdpMLineIndex === 0) { - iceTransport.start(iceGatherer, remoteIceParameters, - isIceLite ? 'controlling' : 'controlled'); - dtlsTransport.start(remoteDtlsParameters); - } - - // Calculate intersection of capabilities. - var params = self._getCommonCapabilities(localCapabilities, - remoteCapabilities); - - // Start the RTCRtpSender. The RTCRtpReceiver for this - // transceiver has already been started in setRemoteDescription. - self._transceive(transceiver, - params.codecs.length > 0, - false); - } - }); - } - - this.localDescription = { - type: description.type, - sdp: description.sdp - }; - switch (description.type) { - case 'offer': - this._updateSignalingState('have-local-offer'); - break; - case 'answer': - this._updateSignalingState('stable'); - break; - default: - throw new TypeError('unsupported type "' + description.type + - '"'); - } - - // If a success callback was provided, emit ICE candidates after it - // has been executed. Otherwise, emit callback after the Promise is - // resolved. - var hasCallback = arguments.length > 1 && - typeof arguments[1] === 'function'; - if (hasCallback) { - var cb = arguments[1]; - window.setTimeout(function() { - cb(); - if (self.iceGatheringState === 'new') { - self.iceGatheringState = 'gathering'; - } - self._emitBufferedCandidates(); - }, 0); - } - var p = Promise.resolve(); - p.then(function() { - if (!hasCallback) { - if (self.iceGatheringState === 'new') { - self.iceGatheringState = 'gathering'; - } - // Usually candidates will be emitted earlier. - window.setTimeout(self._emitBufferedCandidates.bind(self), 500); - } - }); - return p; - }; - - window.RTCPeerConnection.prototype.setRemoteDescription = - function(description) { - var self = this; - var stream = new MediaStream(); - var receiverList = []; - var sections = SDPUtils.splitSections(description.sdp); - var sessionpart = sections.shift(); - var isIceLite = SDPUtils.matchPrefix(sessionpart, - 'a=ice-lite').length > 0; - this.usingBundle = SDPUtils.matchPrefix(sessionpart, - 'a=group:BUNDLE ').length > 0; - sections.forEach(function(mediaSection, sdpMLineIndex) { - var lines = SDPUtils.splitLines(mediaSection); - var mline = lines[0].substr(2).split(' '); - var kind = mline[0]; - var rejected = mline[1] === '0'; - var direction = SDPUtils.getDirection(mediaSection, sessionpart); - - var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:'); - if (mid.length) { - mid = mid[0].substr(6); - } else { - mid = SDPUtils.generateIdentifier(); - } - - // Reject datachannels which are not implemented yet. - if (kind === 'application' && mline[2] === 'DTLS/SCTP') { - self.transceivers[sdpMLineIndex] = { - mid: mid, - isDatachannel: true - }; - return; - } - - var transceiver; - var iceGatherer; - var iceTransport; - var dtlsTransport; - var rtpSender; - var rtpReceiver; - var sendEncodingParameters; - var recvEncodingParameters; - var localCapabilities; - - var track; - // FIXME: ensure the mediaSection has rtcp-mux set. - var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection); - var remoteIceParameters; - var remoteDtlsParameters; - if (!rejected) { - remoteIceParameters = SDPUtils.getIceParameters(mediaSection, - sessionpart); - remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection, - sessionpart); - remoteDtlsParameters.role = 'client'; - } - recvEncodingParameters = - SDPUtils.parseRtpEncodingParameters(mediaSection); - - var cname; - // Gets the first SSRC. Note that with RTX there might be multiple - // SSRCs. - var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:') - .map(function(line) { - return SDPUtils.parseSsrcMedia(line); - }) - .filter(function(obj) { - return obj.attribute === 'cname'; - })[0]; - if (remoteSsrc) { - cname = remoteSsrc.value; - } - - var isComplete = SDPUtils.matchPrefix(mediaSection, - 'a=end-of-candidates', sessionpart).length > 0; - var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:') - .map(function(cand) { - return SDPUtils.parseCandidate(cand); - }) - .filter(function(cand) { - return cand.component === '1'; - }); - if (description.type === 'offer' && !rejected) { - var transports = self.usingBundle && sdpMLineIndex > 0 ? { - iceGatherer: self.transceivers[0].iceGatherer, - iceTransport: self.transceivers[0].iceTransport, - dtlsTransport: self.transceivers[0].dtlsTransport - } : self._createIceAndDtlsTransports(mid, sdpMLineIndex); - - if (isComplete) { - transports.iceTransport.setRemoteCandidates(cands); - } - - localCapabilities = RTCRtpReceiver.getCapabilities(kind); - - // filter RTX until additional stuff needed for RTX is implemented - // in adapter.js - localCapabilities.codecs = localCapabilities.codecs.filter( - function(codec) { - return codec.name !== 'rtx'; - }); - - sendEncodingParameters = [{ - ssrc: (2 * sdpMLineIndex + 2) * 1001 - }]; - - rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind); - - track = rtpReceiver.track; - receiverList.push([track, rtpReceiver]); - // FIXME: not correct when there are multiple streams but that is - // not currently supported in this shim. - stream.addTrack(track); - - // FIXME: look at direction. - if (self.localStreams.length > 0 && - self.localStreams[0].getTracks().length >= sdpMLineIndex) { - var localTrack; - if (kind === 'audio') { - localTrack = self.localStreams[0].getAudioTracks()[0]; - } else if (kind === 'video') { - localTrack = self.localStreams[0].getVideoTracks()[0]; - } - if (localTrack) { - rtpSender = new RTCRtpSender(localTrack, - transports.dtlsTransport); - } - } - - self.transceivers[sdpMLineIndex] = { - iceGatherer: transports.iceGatherer, - iceTransport: transports.iceTransport, - dtlsTransport: transports.dtlsTransport, - localCapabilities: localCapabilities, - remoteCapabilities: remoteCapabilities, - rtpSender: rtpSender, - rtpReceiver: rtpReceiver, - kind: kind, - mid: mid, - cname: cname, - sendEncodingParameters: sendEncodingParameters, - recvEncodingParameters: recvEncodingParameters - }; - // Start the RTCRtpReceiver now. The RTPSender is started in - // setLocalDescription. - self._transceive(self.transceivers[sdpMLineIndex], - false, - direction === 'sendrecv' || direction === 'sendonly'); - } else if (description.type === 'answer' && !rejected) { - transceiver = self.transceivers[sdpMLineIndex]; - iceGatherer = transceiver.iceGatherer; - iceTransport = transceiver.iceTransport; - dtlsTransport = transceiver.dtlsTransport; - rtpSender = transceiver.rtpSender; - rtpReceiver = transceiver.rtpReceiver; - sendEncodingParameters = transceiver.sendEncodingParameters; - localCapabilities = transceiver.localCapabilities; - - self.transceivers[sdpMLineIndex].recvEncodingParameters = - recvEncodingParameters; - self.transceivers[sdpMLineIndex].remoteCapabilities = - remoteCapabilities; - self.transceivers[sdpMLineIndex].cname = cname; - - if ((isIceLite || isComplete) && cands.length) { - iceTransport.setRemoteCandidates(cands); - } - if (!self.usingBundle || sdpMLineIndex === 0) { - iceTransport.start(iceGatherer, remoteIceParameters, - 'controlling'); - dtlsTransport.start(remoteDtlsParameters); - } - - self._transceive(transceiver, - direction === 'sendrecv' || direction === 'recvonly', - direction === 'sendrecv' || direction === 'sendonly'); - - if (rtpReceiver && - (direction === 'sendrecv' || direction === 'sendonly')) { - track = rtpReceiver.track; - receiverList.push([track, rtpReceiver]); - stream.addTrack(track); - } else { - // FIXME: actually the receiver should be created later. - delete transceiver.rtpReceiver; - } - } - }); - - this.remoteDescription = { - type: description.type, - sdp: description.sdp - }; - switch (description.type) { - case 'offer': - this._updateSignalingState('have-remote-offer'); - break; - case 'answer': - this._updateSignalingState('stable'); - break; - default: - throw new TypeError('unsupported type "' + description.type + - '"'); - } - if (stream.getTracks().length) { - self.remoteStreams.push(stream); - window.setTimeout(function() { - var event = new Event('addstream'); - event.stream = stream; - self.dispatchEvent(event); - if (self.onaddstream !== null) { - window.setTimeout(function() { - self.onaddstream(event); - }, 0); - } - - receiverList.forEach(function(item) { - var track = item[0]; - var receiver = item[1]; - var trackEvent = new Event('track'); - trackEvent.track = track; - trackEvent.receiver = receiver; - trackEvent.streams = [stream]; - self.dispatchEvent(event); - if (self.ontrack !== null) { - window.setTimeout(function() { - self.ontrack(trackEvent); - }, 0); - } - }); - }, 0); - } - if (arguments.length > 1 && typeof arguments[1] === 'function') { - window.setTimeout(arguments[1], 0); - } - return Promise.resolve(); - }; - - window.RTCPeerConnection.prototype.close = function() { - this.transceivers.forEach(function(transceiver) { - /* not yet - if (transceiver.iceGatherer) { - transceiver.iceGatherer.close(); - } - */ - if (transceiver.iceTransport) { - transceiver.iceTransport.stop(); - } - if (transceiver.dtlsTransport) { - transceiver.dtlsTransport.stop(); - } - if (transceiver.rtpSender) { - transceiver.rtpSender.stop(); - } - if (transceiver.rtpReceiver) { - transceiver.rtpReceiver.stop(); - } - }); - // FIXME: clean up tracks, local streams, remote streams, etc - this._updateSignalingState('closed'); - }; - - // Update the signaling state. - window.RTCPeerConnection.prototype._updateSignalingState = - function(newState) { - this.signalingState = newState; - var event = new Event('signalingstatechange'); - this.dispatchEvent(event); - if (this.onsignalingstatechange !== null) { - this.onsignalingstatechange(event); - } - }; - - // Determine whether to fire the negotiationneeded event. - window.RTCPeerConnection.prototype._maybeFireNegotiationNeeded = - function() { - // Fire away (for now). - var event = new Event('negotiationneeded'); - this.dispatchEvent(event); - if (this.onnegotiationneeded !== null) { - this.onnegotiationneeded(event); - } - }; - - // Update the connection state. - window.RTCPeerConnection.prototype._updateConnectionState = function() { - var self = this; - var newState; - var states = { - 'new': 0, - closed: 0, - connecting: 0, - checking: 0, - connected: 0, - completed: 0, - failed: 0 - }; - this.transceivers.forEach(function(transceiver) { - states[transceiver.iceTransport.state]++; - states[transceiver.dtlsTransport.state]++; - }); - // ICETransport.completed and connected are the same for this purpose. - states.connected += states.completed; - - newState = 'new'; - if (states.failed > 0) { - newState = 'failed'; - } else if (states.connecting > 0 || states.checking > 0) { - newState = 'connecting'; - } else if (states.disconnected > 0) { - newState = 'disconnected'; - } else if (states.new > 0) { - newState = 'new'; - } else if (states.connected > 0 || states.completed > 0) { - newState = 'connected'; - } - - if (newState !== self.iceConnectionState) { - self.iceConnectionState = newState; - var event = new Event('iceconnectionstatechange'); - this.dispatchEvent(event); - if (this.oniceconnectionstatechange !== null) { - this.oniceconnectionstatechange(event); - } - } - }; - - window.RTCPeerConnection.prototype.createOffer = function() { - var self = this; - if (this._pendingOffer) { - throw new Error('createOffer called while there is a pending offer.'); - } - var offerOptions; - if (arguments.length === 1 && typeof arguments[0] !== 'function') { - offerOptions = arguments[0]; - } else if (arguments.length === 3) { - offerOptions = arguments[2]; - } - - var tracks = []; - var numAudioTracks = 0; - var numVideoTracks = 0; - // Default to sendrecv. - if (this.localStreams.length) { - numAudioTracks = this.localStreams[0].getAudioTracks().length; - numVideoTracks = this.localStreams[0].getVideoTracks().length; - } - // Determine number of audio and video tracks we need to send/recv. - if (offerOptions) { - // Reject Chrome legacy constraints. - if (offerOptions.mandatory || offerOptions.optional) { - throw new TypeError( - 'Legacy mandatory/optional constraints not supported.'); - } - if (offerOptions.offerToReceiveAudio !== undefined) { - numAudioTracks = offerOptions.offerToReceiveAudio; - } - if (offerOptions.offerToReceiveVideo !== undefined) { - numVideoTracks = offerOptions.offerToReceiveVideo; - } - } - if (this.localStreams.length) { - // Push local streams. - this.localStreams[0].getTracks().forEach(function(track) { - tracks.push({ - kind: track.kind, - track: track, - wantReceive: track.kind === 'audio' ? - numAudioTracks > 0 : numVideoTracks > 0 - }); - if (track.kind === 'audio') { - numAudioTracks--; - } else if (track.kind === 'video') { - numVideoTracks--; - } - }); - } - // Create M-lines for recvonly streams. - while (numAudioTracks > 0 || numVideoTracks > 0) { - if (numAudioTracks > 0) { - tracks.push({ - kind: 'audio', - wantReceive: true - }); - numAudioTracks--; - } - if (numVideoTracks > 0) { - tracks.push({ - kind: 'video', - wantReceive: true - }); - numVideoTracks--; - } - } - - var sdp = SDPUtils.writeSessionBoilerplate(); - var transceivers = []; - tracks.forEach(function(mline, sdpMLineIndex) { - // For each track, create an ice gatherer, ice transport, - // dtls transport, potentially rtpsender and rtpreceiver. - var track = mline.track; - var kind = mline.kind; - var mid = SDPUtils.generateIdentifier(); - - var transports = self.usingBundle && sdpMLineIndex > 0 ? { - iceGatherer: transceivers[0].iceGatherer, - iceTransport: transceivers[0].iceTransport, - dtlsTransport: transceivers[0].dtlsTransport - } : self._createIceAndDtlsTransports(mid, sdpMLineIndex); - - var localCapabilities = RTCRtpSender.getCapabilities(kind); - // filter RTX until additional stuff needed for RTX is implemented - // in adapter.js - localCapabilities.codecs = localCapabilities.codecs.filter( - function(codec) { - return codec.name !== 'rtx'; - }); - localCapabilities.codecs.forEach(function(codec) { - // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552 - // by adding level-asymmetry-allowed=1 - if (codec.name === 'H264' && - codec.parameters['level-asymmetry-allowed'] === undefined) { - codec.parameters['level-asymmetry-allowed'] = '1'; - } - }); - - var rtpSender; - var rtpReceiver; - - // generate an ssrc now, to be used later in rtpSender.send - var sendEncodingParameters = [{ - ssrc: (2 * sdpMLineIndex + 1) * 1001 - }]; - if (track) { - rtpSender = new RTCRtpSender(track, transports.dtlsTransport); - } - - if (mline.wantReceive) { - rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind); - } - - transceivers[sdpMLineIndex] = { - iceGatherer: transports.iceGatherer, - iceTransport: transports.iceTransport, - dtlsTransport: transports.dtlsTransport, - localCapabilities: localCapabilities, - remoteCapabilities: null, - rtpSender: rtpSender, - rtpReceiver: rtpReceiver, - kind: kind, - mid: mid, - sendEncodingParameters: sendEncodingParameters, - recvEncodingParameters: null - }; - }); - if (this.usingBundle) { - sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) { - return t.mid; - }).join(' ') + '\r\n'; - } - tracks.forEach(function(mline, sdpMLineIndex) { - var transceiver = transceivers[sdpMLineIndex]; - sdp += SDPUtils.writeMediaSection(transceiver, - transceiver.localCapabilities, 'offer', self.localStreams[0]); - }); - - this._pendingOffer = transceivers; - var desc = new RTCSessionDescription({ - type: 'offer', - sdp: sdp - }); - if (arguments.length && typeof arguments[0] === 'function') { - window.setTimeout(arguments[0], 0, desc); - } - return Promise.resolve(desc); - }; - - window.RTCPeerConnection.prototype.createAnswer = function() { - var self = this; - - var sdp = SDPUtils.writeSessionBoilerplate(); - if (this.usingBundle) { - sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) { - return t.mid; - }).join(' ') + '\r\n'; - } - this.transceivers.forEach(function(transceiver) { - if (transceiver.isDatachannel) { - sdp += 'm=application 0 DTLS/SCTP 5000\r\n' + - 'c=IN IP4 0.0.0.0\r\n' + - 'a=mid:' + transceiver.mid + '\r\n'; - return; - } - // Calculate intersection of capabilities. - var commonCapabilities = self._getCommonCapabilities( - transceiver.localCapabilities, - transceiver.remoteCapabilities); - - sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities, - 'answer', self.localStreams[0]); - }); - - var desc = new RTCSessionDescription({ - type: 'answer', - sdp: sdp - }); - if (arguments.length && typeof arguments[0] === 'function') { - window.setTimeout(arguments[0], 0, desc); - } - return Promise.resolve(desc); - }; - - window.RTCPeerConnection.prototype.addIceCandidate = function(candidate) { - if (!candidate) { - this.transceivers.forEach(function(transceiver) { - transceiver.iceTransport.addRemoteCandidate({}); - }); - } else { - var mLineIndex = candidate.sdpMLineIndex; - if (candidate.sdpMid) { - for (var i = 0; i < this.transceivers.length; i++) { - if (this.transceivers[i].mid === candidate.sdpMid) { - mLineIndex = i; - break; - } - } - } - var transceiver = this.transceivers[mLineIndex]; - if (transceiver) { - var cand = Object.keys(candidate.candidate).length > 0 ? - SDPUtils.parseCandidate(candidate.candidate) : {}; - // Ignore Chrome's invalid candidates since Edge does not like them. - if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) { - return; - } - // Ignore RTCP candidates, we assume RTCP-MUX. - if (cand.component !== '1') { - return; - } - // A dirty hack to make samples work. - if (cand.type === 'endOfCandidates') { - cand = {}; - } - transceiver.iceTransport.addRemoteCandidate(cand); - - // update the remoteDescription. - var sections = SDPUtils.splitSections(this.remoteDescription.sdp); - sections[mLineIndex + 1] += (cand.type ? candidate.candidate.trim() - : 'a=end-of-candidates') + '\r\n'; - this.remoteDescription.sdp = sections.join(''); - } - } - if (arguments.length > 1 && typeof arguments[1] === 'function') { - window.setTimeout(arguments[1], 0); - } - return Promise.resolve(); - }; - - window.RTCPeerConnection.prototype.getStats = function() { - var promises = []; - this.transceivers.forEach(function(transceiver) { - ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport', - 'dtlsTransport'].forEach(function(method) { - if (transceiver[method]) { - promises.push(transceiver[method].getStats()); - } - }); - }); - var cb = arguments.length > 1 && typeof arguments[1] === 'function' && - arguments[1]; - return new Promise(function(resolve) { - // shim getStats with maplike support - var results = new Map(); - Promise.all(promises).then(function(res) { - res.forEach(function(result) { - Object.keys(result).forEach(function(id) { - results.set(id, result[id]); - results[id] = result[id]; - }); - }); - if (cb) { - window.setTimeout(cb, 0, results); - } - resolve(results); - }); - }); - }; - } -}; - -// Expose public methods. -module.exports = { - shimPeerConnection: edgeShim.shimPeerConnection, - shimGetUserMedia: require('./getusermedia') -}; - -},{"../utils":41,"./getusermedia":37,"sdp":184}],37:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; - -// Expose public methods. -module.exports = function() { - var shimError_ = function(e) { - return { - name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name, - message: e.message, - constraint: e.constraint, - toString: function() { - return this.name; - } - }; - }; - - // getUserMedia error shim. - var origGetUserMedia = navigator.mediaDevices.getUserMedia. - bind(navigator.mediaDevices); - navigator.mediaDevices.getUserMedia = function(c) { - return origGetUserMedia(c).catch(function(e) { - return Promise.reject(shimError_(e)); - }); - }; -}; - -},{}],38:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; - -var browserDetails = require('../utils').browserDetails; - -var firefoxShim = { - shimOnTrack: function() { - if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in - window.RTCPeerConnection.prototype)) { - Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { - get: function() { - return this._ontrack; - }, - set: function(f) { - if (this._ontrack) { - this.removeEventListener('track', this._ontrack); - this.removeEventListener('addstream', this._ontrackpoly); - } - this.addEventListener('track', this._ontrack = f); - this.addEventListener('addstream', this._ontrackpoly = function(e) { - e.stream.getTracks().forEach(function(track) { - var event = new Event('track'); - event.track = track; - event.receiver = {track: track}; - event.streams = [e.stream]; - this.dispatchEvent(event); - }.bind(this)); - }.bind(this)); - } - }); - } - }, - - shimSourceObject: function() { - // Firefox has supported mozSrcObject since FF22, unprefixed in 42. - if (typeof window === 'object') { - if (window.HTMLMediaElement && - !('srcObject' in window.HTMLMediaElement.prototype)) { - // Shim the srcObject property, once, when HTMLMediaElement is found. - Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', { - get: function() { - return this.mozSrcObject; - }, - set: function(stream) { - this.mozSrcObject = stream; - } - }); - } - } - }, - - shimPeerConnection: function() { - if (typeof window !== 'object' || !(window.RTCPeerConnection || - window.mozRTCPeerConnection)) { - return; // probably media.peerconnection.enabled=false in about:config - } - // The RTCPeerConnection object. - if (!window.RTCPeerConnection) { - window.RTCPeerConnection = function(pcConfig, pcConstraints) { - if (browserDetails.version < 38) { - // .urls is not supported in FF < 38. - // create RTCIceServers with a single url. - if (pcConfig && pcConfig.iceServers) { - var newIceServers = []; - for (var i = 0; i < pcConfig.iceServers.length; i++) { - var server = pcConfig.iceServers[i]; - if (server.hasOwnProperty('urls')) { - for (var j = 0; j < server.urls.length; j++) { - var newServer = { - url: server.urls[j] - }; - if (server.urls[j].indexOf('turn') === 0) { - newServer.username = server.username; - newServer.credential = server.credential; - } - newIceServers.push(newServer); - } - } else { - newIceServers.push(pcConfig.iceServers[i]); - } - } - pcConfig.iceServers = newIceServers; - } - } - return new mozRTCPeerConnection(pcConfig, pcConstraints); - }; - window.RTCPeerConnection.prototype = mozRTCPeerConnection.prototype; - - // wrap static methods. Currently just generateCertificate. - if (mozRTCPeerConnection.generateCertificate) { - Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', { - get: function() { - return mozRTCPeerConnection.generateCertificate; - } - }); - } - - window.RTCSessionDescription = mozRTCSessionDescription; - window.RTCIceCandidate = mozRTCIceCandidate; - } - - // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. - ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'] - .forEach(function(method) { - var nativeMethod = RTCPeerConnection.prototype[method]; - RTCPeerConnection.prototype[method] = function() { - arguments[0] = new ((method === 'addIceCandidate') ? - RTCIceCandidate : RTCSessionDescription)(arguments[0]); - return nativeMethod.apply(this, arguments); - }; - }); - - // support for addIceCandidate(null or undefined) - var nativeAddIceCandidate = - RTCPeerConnection.prototype.addIceCandidate; - RTCPeerConnection.prototype.addIceCandidate = function() { - if (!arguments[0]) { - if (arguments[1]) { - arguments[1].apply(null); - } - return Promise.resolve(); - } - return nativeAddIceCandidate.apply(this, arguments); - }; - - if (browserDetails.version < 48) { - // shim getStats with maplike support - var makeMapStats = function(stats) { - var map = new Map(); - Object.keys(stats).forEach(function(key) { - map.set(key, stats[key]); - map[key] = stats[key]; - }); - return map; - }; - - var nativeGetStats = RTCPeerConnection.prototype.getStats; - RTCPeerConnection.prototype.getStats = function(selector, onSucc, onErr) { - return nativeGetStats.apply(this, [selector || null]) - .then(function(stats) { - return makeMapStats(stats); - }) - .then(onSucc, onErr); - }; - } - } -}; - -// Expose public methods. -module.exports = { - shimOnTrack: firefoxShim.shimOnTrack, - shimSourceObject: firefoxShim.shimSourceObject, - shimPeerConnection: firefoxShim.shimPeerConnection, - shimGetUserMedia: require('./getusermedia') -}; - -},{"../utils":41,"./getusermedia":39}],39:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; - -var logging = require('../utils').log; -var browserDetails = require('../utils').browserDetails; - -// Expose public methods. -module.exports = function() { - var shimError_ = function(e) { - return { - name: { - SecurityError: 'NotAllowedError', - PermissionDeniedError: 'NotAllowedError' - }[e.name] || e.name, - message: { - 'The operation is insecure.': 'The request is not allowed by the ' + - 'user agent or the platform in the current context.' - }[e.message] || e.message, - constraint: e.constraint, - toString: function() { - return this.name + (this.message && ': ') + this.message; - } - }; - }; - - // getUserMedia constraints shim. - var getUserMedia_ = function(constraints, onSuccess, onError) { - var constraintsToFF37_ = function(c) { - if (typeof c !== 'object' || c.require) { - return c; - } - var require = []; - Object.keys(c).forEach(function(key) { - if (key === 'require' || key === 'advanced' || key === 'mediaSource') { - return; - } - var r = c[key] = (typeof c[key] === 'object') ? - c[key] : {ideal: c[key]}; - if (r.min !== undefined || - r.max !== undefined || r.exact !== undefined) { - require.push(key); - } - if (r.exact !== undefined) { - if (typeof r.exact === 'number') { - r. min = r.max = r.exact; - } else { - c[key] = r.exact; - } - delete r.exact; - } - if (r.ideal !== undefined) { - c.advanced = c.advanced || []; - var oc = {}; - if (typeof r.ideal === 'number') { - oc[key] = {min: r.ideal, max: r.ideal}; - } else { - oc[key] = r.ideal; - } - c.advanced.push(oc); - delete r.ideal; - if (!Object.keys(r).length) { - delete c[key]; - } - } - }); - if (require.length) { - c.require = require; - } - return c; - }; - constraints = JSON.parse(JSON.stringify(constraints)); - if (browserDetails.version < 38) { - logging('spec: ' + JSON.stringify(constraints)); - if (constraints.audio) { - constraints.audio = constraintsToFF37_(constraints.audio); - } - if (constraints.video) { - constraints.video = constraintsToFF37_(constraints.video); - } - logging('ff37: ' + JSON.stringify(constraints)); - } - return navigator.mozGetUserMedia(constraints, onSuccess, function(e) { - onError(shimError_(e)); - }); - }; - - // Returns the result of getUserMedia as a Promise. - var getUserMediaPromise_ = function(constraints) { - return new Promise(function(resolve, reject) { - getUserMedia_(constraints, resolve, reject); - }); - }; - - // Shim for mediaDevices on older versions. - if (!navigator.mediaDevices) { - navigator.mediaDevices = {getUserMedia: getUserMediaPromise_, - addEventListener: function() { }, - removeEventListener: function() { } - }; - } - navigator.mediaDevices.enumerateDevices = - navigator.mediaDevices.enumerateDevices || function() { - return new Promise(function(resolve) { - var infos = [ - {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''}, - {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''} - ]; - resolve(infos); - }); - }; - - if (browserDetails.version < 41) { - // Work around http://bugzil.la/1169665 - var orgEnumerateDevices = - navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices); - navigator.mediaDevices.enumerateDevices = function() { - return orgEnumerateDevices().then(undefined, function(e) { - if (e.name === 'NotFoundError') { - return []; - } - throw e; - }); - }; - } - if (browserDetails.version < 49) { - var origGetUserMedia = navigator.mediaDevices.getUserMedia. - bind(navigator.mediaDevices); - navigator.mediaDevices.getUserMedia = function(c) { - return origGetUserMedia(c).then(function(stream) { - // Work around https://bugzil.la/802326 - if (c.audio && !stream.getAudioTracks().length || - c.video && !stream.getVideoTracks().length) { - stream.getTracks().forEach(function(track) { - track.stop(); - }); - throw new DOMException('The object can not be found here.', - 'NotFoundError'); - } - return stream; - }, function(e) { - return Promise.reject(shimError_(e)); - }); - }; - } - navigator.getUserMedia = function(constraints, onSuccess, onError) { - if (browserDetails.version < 44) { - return getUserMedia_(constraints, onSuccess, onError); - } - // Replace Firefox 44+'s deprecation warning with unprefixed version. - console.warn('navigator.getUserMedia has been replaced by ' + - 'navigator.mediaDevices.getUserMedia'); - navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError); - }; -}; - -},{"../utils":41}],40:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ -'use strict'; -var safariShim = { - // TODO: DrAlex, should be here, double check against LayoutTests - // shimOnTrack: function() { }, - - // TODO: once the back-end for the mac port is done, add. - // TODO: check for webkitGTK+ - // shimPeerConnection: function() { }, - - shimGetUserMedia: function() { - navigator.getUserMedia = navigator.webkitGetUserMedia; - } -}; - -// Expose public methods. -module.exports = { - shimGetUserMedia: safariShim.shimGetUserMedia - // TODO - // shimOnTrack: safariShim.shimOnTrack, - // shimPeerConnection: safariShim.shimPeerConnection -}; - -},{}],41:[function(require,module,exports){ -/* - * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ - /* eslint-env node */ -'use strict'; - -var logDisabled_ = true; - -// Utility methods. -var utils = { - disableLog: function(bool) { - if (typeof bool !== 'boolean') { - return new Error('Argument type: ' + typeof bool + - '. Please use a boolean.'); - } - logDisabled_ = bool; - return (bool) ? 'adapter.js logging disabled' : - 'adapter.js logging enabled'; - }, - - log: function() { - if (typeof window === 'object') { - if (logDisabled_) { - return; - } - if (typeof console !== 'undefined' && typeof console.log === 'function') { - console.log.apply(console, arguments); - } - } - }, - - /** - * Extract browser version out of the provided user agent string. - * - * @param {!string} uastring userAgent string. - * @param {!string} expr Regular expression used as match criteria. - * @param {!number} pos position in the version string to be returned. - * @return {!number} browser version. - */ - extractVersion: function(uastring, expr, pos) { - var match = uastring.match(expr); - return match && match.length >= pos && parseInt(match[pos], 10); - }, - - /** - * Browser detector. - * - * @return {object} result containing browser and version - * properties. - */ - detectBrowser: function() { - // Returned result object. - var result = {}; - result.browser = null; - result.version = null; - - // Fail early if it's not a browser - if (typeof window === 'undefined' || !window.navigator) { - result.browser = 'Not a browser.'; - return result; - } - - // Firefox. - if (navigator.mozGetUserMedia) { - result.browser = 'firefox'; - result.version = this.extractVersion(navigator.userAgent, - /Firefox\/([0-9]+)\./, 1); - - // all webkit-based browsers - } else if (navigator.webkitGetUserMedia) { - // Chrome, Chromium, Webview, Opera, all use the chrome shim for now - if (window.webkitRTCPeerConnection) { - result.browser = 'chrome'; - result.version = this.extractVersion(navigator.userAgent, - /Chrom(e|ium)\/([0-9]+)\./, 2); - - // Safari or unknown webkit-based - // for the time being Safari has support for MediaStreams but not webRTC - } else { - // Safari UA substrings of interest for reference: - // - webkit version: AppleWebKit/602.1.25 (also used in Op,Cr) - // - safari UI version: Version/9.0.3 (unique to Safari) - // - safari UI webkit version: Safari/601.4.4 (also used in Op,Cr) - // - // if the webkit version and safari UI webkit versions are equals, - // ... this is a stable version. - // - // only the internal webkit version is important today to know if - // media streams are supported - // - if (navigator.userAgent.match(/Version\/(\d+).(\d+)/)) { - result.browser = 'safari'; - result.version = this.extractVersion(navigator.userAgent, - /AppleWebKit\/([0-9]+)\./, 1); - - // unknown webkit-based browser - } else { - result.browser = 'Unsupported webkit-based browser ' + - 'with GUM support but no WebRTC support.'; - return result; - } - } - - // Edge. - } else if (navigator.mediaDevices && - navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { - result.browser = 'edge'; - result.version = this.extractVersion(navigator.userAgent, - /Edge\/(\d+).(\d+)$/, 2); - - // Default fallthrough: not supported. - } else { - result.browser = 'Not a supported browser.'; - return result; - } - - return result; - } -}; - -// Export. -module.exports = { - log: utils.log, - disableLog: utils.disableLog, - browserDetails: utils.detectBrowser(), - extractVersion: utils.extractVersion -}; - -},{}],42:[function(require,module,exports){ -var createHash = require('create-hash'); -var createHmac = require('create-hmac'); -var getHashes = require('./lib/get-hashes'); - -var mapping = { - md2: 'md2', - md5: 'md5', - 'sha-1': 'sha1', - 'sha-224': 'sha224', - 'sha-256': 'sha256', - 'sha-384': 'sha384', - 'sha-512': 'sha512' -}; - -var names = Object.keys(mapping); - - -exports.getHashes = function () { - var result = []; - var available = getHashes(); - for (var i = 0, len = names.length; i < len; i++) { - if (available.indexOf(mapping[names[i]]) >= 0) { - result.push(names[i]); - } - } - return result; -}; - -exports.createHash = function (algorithm) { - algorithm = algorithm.toLowerCase(); - if (mapping[algorithm]) { - algorithm = mapping[algorithm]; - } - return createHash(algorithm); -}; - -exports.createHmac = function (algorithm, key) { - algorithm = algorithm.toLowerCase(); - if (mapping[algorithm]) { - algorithm = mapping[algorithm]; - } - return createHmac(algorithm, key); -}; - -},{"./lib/get-hashes":43,"create-hash":23,"create-hmac":26}],43:[function(require,module,exports){ -module.exports = function () { - return ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160']; -}; - -},{}],44:[function(require,module,exports){ -exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] - - i += d - - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen - for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen - for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} - - if (e === 0) { - e = 1 - eBias - } else if (e === eMax) { - return m ? NaN : ((s ? -1 : 1) * Infinity) - } else { - m = m + Math.pow(2, mLen) - e = e - eBias - } - return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} - -exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 - - value = Math.abs(value) - - if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 - e = eMax - } else { - e = Math.floor(Math.log(value) / Math.LN2) - if (value * (c = Math.pow(2, -e)) < 1) { - e-- - c *= 2 - } - if (e + eBias >= 1) { - value += rt / c - } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } - - if (e + eBias >= eMax) { - m = 0 - e = eMax - } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen) - e = e + eBias - } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) - e = 0 - } - } - - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} - - buffer[offset + i - d] |= s * 128 -} - -},{}],45:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],46:[function(require,module,exports){ -module.exports = intersect; - -function intersect (a, b) { - var res = []; - for (var i = 0; i < a.length; i++) { - if (indexOf(b, a[i]) > -1) res.push(a[i]); - } - return res; -} - -intersect.big = function(a, b) { - var ret = []; - var temp = {}; - - for (var i = 0; i < b.length; i++) { - temp[b[i]] = true; - } - for (var i = 0; i < a.length; i++) { - if (temp[a[i]]) ret.push(a[i]); - } - - return ret; -} - -function indexOf(arr, el) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] === el) return i; - } - return -1; -} - -},{}],47:[function(require,module,exports){ -/*! - * Determine if an object is a Buffer - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -// The _isBuffer check is for Safari 5-7 support, because it's missing -// Object.prototype.constructor. Remove this eventually -module.exports = function (obj) { - return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) -} - -function isBuffer (obj) { - return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) -} - -// For Node v0.10 support. Remove this eventually. -function isSlowBuffer (obj) { - return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) -} - -},{}],48:[function(require,module,exports){ -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; -}; - -},{}],49:[function(require,module,exports){ -var util = require('util'); -var extend = require('extend-object'); -var BaseSession = require('jingle-session'); -var RTCPeerConnection = require('rtcpeerconnection'); -var FileTransfer = require('filetransfer/hashed'); - - -function FileTransferSession(opts) { - BaseSession.call(this, opts); - - this.pc = new RTCPeerConnection({ - iceServers: opts.iceServers || [], - useJingle: true - }, opts.constraints || {}); - - this.pc.on('ice', this.onIceCandidate.bind(this)); - this.pc.on('iceConnectionStateChange', this.onIceStateChange.bind(this)); - this.pc.on('addChannel', this.onChannelAdded.bind(this)); - - this.sender = null; - this.receiver = null; -} - - -util.inherits(FileTransferSession, BaseSession); - - -FileTransferSession.prototype = extend(FileTransferSession.prototype, { - - // ---------------------------------------------------------------- - // Session control methods - // ---------------------------------------------------------------- - - start: function (file) { - var self = this; - this.state = 'pending'; - - this.pc.isInitiator = true; - - this.sender = new FileTransfer.Sender(); - this.sender.on('progress', function (sent, size) { - self._log('info', 'Send progress ' + sent + '/' + size); - }); - this.sender.on('sentFile', function (meta) { - self._log('info', 'Sent file', meta.name); - - var content = self.pc.localDescription.contents[0]; - delete content.transport; - - content.application = { - applicationType: 'filetransfer', - offer: { - hash: { - algo: meta.algo, - value: meta.hash - } - } - }; - - self.send('description-info', { - contents: [content] - }); - self.emit('sentFile', self, meta); - }); - - var sendChannel = this.pc.createDataChannel('filetransfer'); - sendChannel.onopen = function () { - self.sender.send(file, sendChannel); - }; - - var constraints = { - mandatory: { - OfferToReceiveAudio: false, - OfferToReceiveVideo: false - } - }; - - this.pc.offer(constraints, function (err, offer) { - if (err) { - self._log('error', 'Could not create WebRTC offer', err); - return self.end('failed-application', true); - } - - offer.jingle.contents[0].application = { - applicationType: 'filetransfer', - offer: { - date: file.lastModifiedDate, - name: file.name, - size: file.size, - hash: { - algo: 'sha-1', - value: '' - } - } - }; - - self.send('session-initiate', offer.jingle); - }); - }, - - accept: function () { - var self = this; - - this._log('info', 'Accepted incoming session'); - - this.state = 'active'; - - this.pc.answer(function (err, answer) { - if (err) { - self._log('error', 'Could not create WebRTC answer', err); - return self.end('failed-application'); - } - self.send('session-accept', answer.jingle); - }); - }, - - end: function (reason, silent) { - this.pc.close(); - BaseSession.prototype.end.call(this, reason, silent); - }, - - maybeReceivedFile: function () { - if (!this.receiver.metadata.hash.value) { - // unknown hash, file transfer not completed - } else if (this.receiver.metadata.hash.value === this.receiver.metadata.actualhash) { - this._log('info', 'File hash matches'); - this.emit('receivedFile', this, this.receivedFile, this.receiver.metadata); - this.end('success'); - } else { - this._log('error', 'File hash does not match'); - this.end('media-error'); - } - }, - - // ---------------------------------------------------------------- - // ICE action handers - // ---------------------------------------------------------------- - - onIceCandidate: function (candidate) { - this._log('info', 'Discovered new ICE candidate', candidate.jingle); - this.send('transport-info', candidate.jingle); - }, - - onIceStateChange: function () { - switch (this.pc.iceConnectionState) { - case 'checking': - this.connectionState = 'connecting'; - break; - case 'completed': - case 'connected': - this.connectionState = 'connected'; - break; - case 'disconnected': - if (this.pc.signalingState === 'stable') { - this.connectionState = 'interrupted'; - } else { - this.connectionState = 'disconnected'; - } - break; - case 'failed': - this.connectionState = 'failed'; - this.end('failed-transport'); - break; - case 'closed': - this.connectionState = 'disconnected'; - break; - } - }, - - onChannelAdded: function (channel) { - this.receiver.receive(null, channel); - }, - - // ---------------------------------------------------------------- - // Jingle action handers - // ---------------------------------------------------------------- - - onSessionInitiate: function (changes, cb) { - var self = this; - - this._log('info', 'Initiating incoming session'); - - this.state = 'pending'; - - this.pc.isInitiator = false; - - var desc = changes.contents[0].application; - - - this.receiver = new FileTransfer.Receiver({hash: desc.offer.hash.algo}); - this.receiver.on('progress', function (received, size) { - self._log('info', 'Receive progress ' + received + '/' + size); - }); - this.receiver.on('receivedFile', function (file) { - self.receivedFile = file; - self.maybeReceivedFile(); - }); - this.receiver.metadata = desc.offer; - - changes.contents[0].application = { - applicationType: 'datachannel' - }; - - this.pc.handleOffer({ - type: 'offer', - jingle: changes - }, function (err) { - if (err) { - self._log('error', 'Could not create WebRTC answer'); - return cb({condition: 'general-error'}); - } - cb(); - }); - }, - - onSessionAccept: function (changes, cb) { - var self = this; - - this.state = 'active'; - - changes.contents[0].application = { - applicationType: 'datachannel' - }; - - this.pc.handleAnswer({ - type: 'answer', - jingle: changes - }, function (err) { - if (err) { - self._log('error', 'Could not process WebRTC answer'); - return cb({condition: 'general-error'}); - } - self.emit('accepted', self); - cb(); - }); - }, - - onSessionTerminate: function (changes, cb) { - this._log('info', 'Terminating session'); - this.pc.close(); - BaseSession.prototype.end.call(this, changes.reason, true); - cb(); - }, - - onDescriptionInfo: function (info, cb) { - var hash = info.contents[0].application.offer.hash; - this.receiver.metadata.hash = hash; - if (this.receiver.metadata.actualhash) { - this.maybeReceivedFile(); - } - cb(); - }, - - onTransportInfo: function (changes, cb) { - this.pc.processIce(changes, function () { - cb(); - }); - } -}); - - -module.exports = FileTransferSession; - -},{"extend-object":28,"filetransfer/hashed":30,"jingle-session":51,"rtcpeerconnection":178,"util":208}],50:[function(require,module,exports){ -var util = require('util'); -var extend = require('extend-object'); -var BaseSession = require('jingle-session'); -var RTCPeerConnection = require('rtcpeerconnection'); - - -function filterContentSources(content, stream) { - if (content.application.applicationType !== 'rtp') { - return; - } - delete content.transport; - delete content.application.payloads; - delete content.application.headerExtensions; - content.application.mux = false; - - if (content.application.sources) { - content.application.sources = content.application.sources.filter(function (source) { - return stream.id === source.parameters[1].value.split(' ')[0]; - }); - } - // remove source groups not related to this stream - if (content.application.sourceGroups) { - content.application.sourceGroups = content.application.sourceGroups.filter(function (group) { - var found = false; - for (var i = 0; i < content.application.sources.length; i++) { - if (content.application.sources[i].ssrc === group.sources[0]) { - found = true; - break; - } - } - return found; - }); - } -} - -function filterUnusedLabels(content) { - // Remove mslabel and label ssrc-specific attributes - var sources = content.application.sources || []; - sources.forEach(function (source) { - source.parameters = source.parameters.filter(function (parameter) { - return !(parameter.key === 'mslabel' || parameter.key === 'label'); - }); - }); -} - - -function MediaSession(opts) { - BaseSession.call(this, opts); - - this.pc = new RTCPeerConnection({ - iceServers: opts.iceServers || [], - useJingle: true - }, opts.constraints || {}); - - this.pc.on('ice', this.onIceCandidate.bind(this, opts)); - this.pc.on('endOfCandidates', this.onIceEndOfCandidates.bind(this, opts)); - this.pc.on('iceConnectionStateChange', this.onIceStateChange.bind(this)); - this.pc.on('addStream', this.onAddStream.bind(this)); - this.pc.on('removeStream', this.onRemoveStream.bind(this)); - this.pc.on('addChannel', this.onAddChannel.bind(this)); - - if (opts.stream) { - this.addStream(opts.stream); - } - - this._ringing = false; -} - - -util.inherits(MediaSession, BaseSession); - - -Object.defineProperties(MediaSession.prototype, { - ringing: { - get: function () { - return this._ringing; - }, - set: function (value) { - if (value !== this._ringing) { - this._ringing = value; - this.emit('change:ringing', value); - } - } - }, - streams: { - get: function () { - if (this.pc.signalingState !== 'closed') { - return this.pc.getRemoteStreams(); - } - return []; - } - } -}); - - -MediaSession.prototype = extend(MediaSession.prototype, { - - // ---------------------------------------------------------------- - // Session control methods - // ---------------------------------------------------------------- - - start: function (offerOptions, next) { - var self = this; - this.state = 'pending'; - - next = next || function () {}; - - this.pc.isInitiator = true; - this.pc.offer(offerOptions, function (err, offer) { - if (err) { - self._log('error', 'Could not create WebRTC offer', err); - return self.end('failed-application', true); - } - - // a workaround for missing a=sendonly - // https://code.google.com/p/webrtc/issues/detail?id=1553 - if (offerOptions && offerOptions.mandatory) { - offer.jingle.contents.forEach(function (content) { - var mediaType = content.application.media; - - if (!content.description || content.application.applicationType !== 'rtp') { - return; - } - - if (!offerOptions.mandatory.OfferToReceiveAudio && mediaType === 'audio') { - content.senders = 'initiator'; - } - - if (!offerOptions.mandatory.OfferToReceiveVideo && mediaType === 'video') { - content.senders = 'initiator'; - } - }); - } - - offer.jingle.contents.forEach(filterUnusedLabels); - - self.send('session-initiate', offer.jingle); - - next(); - }); - }, - - accept: function (opts, next) { - var self = this; - - // support calling with accept(next) or accept(opts, next) - if (arguments.length === 1 && typeof opts === 'function') { - next = opts; - opts = {}; - } - next = next || function () {}; - opts = opts || {}; - - var constraints = opts.constraints || { - mandatory: { - OfferToReceiveAudio: true, - OfferToReceiveVideo: true - } - }; - - this._log('info', 'Accepted incoming session'); - - this.state = 'active'; - - this.pc.answer(constraints, function (err, answer) { - if (err) { - self._log('error', 'Could not create WebRTC answer', err); - return self.end('failed-application'); - } - - answer.jingle.contents.forEach(filterUnusedLabels); - - self.send('session-accept', answer.jingle); - - next(); - }); - }, - - end: function (reason, silent) { - var self = this; - this.streams.forEach(function (stream) { - self.onRemoveStream({stream: stream}); - }); - this.pc.close(); - BaseSession.prototype.end.call(this, reason, silent); - }, - - ring: function () { - this._log('info', 'Ringing on incoming session'); - this.ringing = true; - this.send('session-info', {ringing: true}); - }, - - mute: function (creator, name) { - this._log('info', 'Muting', name); - - this.send('session-info', { - mute: { - creator: creator, - name: name - } - }); - }, - - unmute: function (creator, name) { - this._log('info', 'Unmuting', name); - this.send('session-info', { - unmute: { - creator: creator, - name: name - } - }); - }, - - hold: function () { - this._log('info', 'Placing on hold'); - this.send('session-info', {hold: true}); - }, - - resume: function () { - this._log('info', 'Resuming from hold'); - this.send('session-info', {active: true}); - }, - - // ---------------------------------------------------------------- - // Stream control methods - // ---------------------------------------------------------------- - - addStream: function (stream, renegotiate, cb) { - var self = this; - - cb = cb || function () {}; - - this.pc.addStream(stream); - - if (!renegotiate) { - return; - } - - this.pc.handleOffer({ - type: 'offer', - jingle: this.pc.remoteDescription - }, function (err) { - if (err) { - self._log('error', 'Could not create offer for adding new stream'); - return cb(err); - } - self.pc.answer(function (err, answer) { - if (err) { - self._log('error', 'Could not create answer for adding new stream'); - return cb(err); - } - answer.jingle.contents.forEach(function (content) { - filterContentSources(content, stream); - }); - answer.jingle.contents = answer.jingle.contents.filter(function (content) { - return content.application.applicationType === 'rtp' && content.application.sources && content.application.sources.length; - }); - delete answer.jingle.groups; - - self.send('source-add', answer.jingle); - cb(); - }); - }); - }, - - addStream2: function (stream, cb) { - this.addStream(stream, true, cb); - }, - - removeStream: function (stream, renegotiate, cb) { - var self = this; - - cb = cb || function () {}; - - if (!renegotiate) { - this.pc.removeStream(stream); - return; - } - - var desc = this.pc.localDescription; - desc.contents.forEach(function (content) { - filterContentSources(content, stream); - }); - desc.contents = desc.contents.filter(function (content) { - return content.application.applicationType === 'rtp' && content.application.sources && content.application.sources.length; - }); - delete desc.groups; - - this.send('source-remove', desc); - this.pc.removeStream(stream); - - this.pc.handleOffer({ - type: 'offer', - jingle: this.pc.remoteDescription - }, function (err) { - if (err) { - self._log('error', 'Could not process offer for removing stream'); - return cb(err); - } - self.pc.answer(function (err) { - if (err) { - self._log('error', 'Could not process answer for removing stream'); - return cb(err); - } - cb(); - }); - }); - }, - - removeStream2: function (stream, cb) { - this.removeStream(stream, true, cb); - }, - - switchStream: function (oldStream, newStream, cb) { - var self = this; - - cb = cb || function () {}; - - var desc = this.pc.localDescription; - desc.contents.forEach(function (content) { - delete content.transport; - delete content.application.payloads; - }); - - this.pc.removeStream(oldStream); - this.send('source-remove', desc); - - this.pc.addStream(newStream); - this.pc.handleOffer({ - type: 'offer', - jingle: this.pc.remoteDescription - }, function (err) { - if (err) { - self._log('error', 'Could not process offer for switching streams'); - return cb(err); - } - self.pc.answer(function (err, answer) { - if (err) { - self._log('error', 'Could not process answer for switching streams'); - return cb(err); - } - answer.jingle.contents.forEach(function (content) { - delete content.transport; - delete content.application.payloads; - }); - self.send('source-add', answer.jingle); - cb(); - }); - }); - }, - - // ---------------------------------------------------------------- - // ICE action handers - // ---------------------------------------------------------------- - - onIceCandidate: function (opts, candidate) { - this._log('info', 'Discovered new ICE candidate', candidate.jingle); - this.send('transport-info', candidate.jingle); - if (opts.signalEndOfCandidates) { - this.lastCandidate = candidate; - } - }, - - onIceEndOfCandidates: function (opts) { - this._log('info', 'ICE end of candidates'); - if (opts.signalEndOfCandidates) { - var endOfCandidates = this.lastCandidate.jingle; - endOfCandidates.contents[0].transport = { - transportType: endOfCandidates.contents[0].transport.transportType, - gatheringComplete: true - }; - this.lastCandidate = null; - this.send('transport-info', endOfCandidates); - } - }, - - onIceStateChange: function () { - switch (this.pc.iceConnectionState) { - case 'checking': - this.connectionState = 'connecting'; - break; - case 'completed': - case 'connected': - this.connectionState = 'connected'; - break; - case 'disconnected': - if (this.pc.signalingState === 'stable') { - this.connectionState = 'interrupted'; - } else { - this.connectionState = 'disconnected'; - } - break; - case 'failed': - this.connectionState = 'failed'; - this.end('failed-transport'); - break; - case 'closed': - this.connectionState = 'disconnected'; - break; - } - }, - - // ---------------------------------------------------------------- - // Stream event handlers - // ---------------------------------------------------------------- - - onAddStream: function (event) { - this._log('info', 'Stream added'); - this.emit('peerStreamAdded', this, event.stream); - }, - - onRemoveStream: function (event) { - this._log('info', 'Stream removed'); - this.emit('peerStreamRemoved', this, event.stream); - }, - - // ---------------------------------------------------------------- - // Jingle action handers - // ---------------------------------------------------------------- - - onSessionInitiate: function (changes, cb) { - var self = this; - - this._log('info', 'Initiating incoming session'); - - this.state = 'pending'; - - this.pc.isInitiator = false; - this.pc.handleOffer({ - type: 'offer', - jingle: changes - }, function (err) { - if (err) { - self._log('error', 'Could not create WebRTC answer'); - return cb({condition: 'general-error'}); - } - cb(); - }); - }, - - onSessionAccept: function (changes, cb) { - var self = this; - - this.state = 'active'; - this.pc.handleAnswer({ - type: 'answer', - jingle: changes - }, function (err) { - if (err) { - self._log('error', 'Could not process WebRTC answer'); - return cb({condition: 'general-error'}); - } - self.emit('accepted', self); - cb(); - }); - }, - - onSessionTerminate: function (changes, cb) { - var self = this; - - this._log('info', 'Terminating session'); - this.streams.forEach(function (stream) { - self.onRemoveStream({stream: stream}); - }); - this.pc.close(); - BaseSession.prototype.end.call(this, changes.reason, true); - - cb(); - }, - - onSessionInfo: function (info, cb) { - if (info.ringing) { - this._log('info', 'Outgoing session is ringing'); - this.ringing = true; - this.emit('ringing', this); - return cb(); - } - - if (info.hold) { - this._log('info', 'On hold'); - this.emit('hold', this); - return cb(); - } - - if (info.active) { - this._log('info', 'Resuming from hold'); - this.emit('resumed', this); - return cb(); - } - - if (info.mute) { - this._log('info', 'Muting', info.mute); - this.emit('mute', this, info.mute); - return cb(); - } - - if (info.unmute) { - this._log('info', 'Unmuting', info.unmute); - this.emit('unmute', this, info.unmute); - return cb(); - } - - cb(); - }, - - onTransportInfo: function (changes, cb) { - this.pc.processIce(changes, function () { - cb(); - }); - }, - - onSourceAdd: function (changes, cb) { - var self = this; - this._log('info', 'Adding new stream source'); - - var newDesc = this.pc.remoteDescription; - this.pc.remoteDescription.contents.forEach(function (content, idx) { - var desc = content.application; - var ssrcs = desc.sources || []; - var groups = desc.sourceGroups || []; - - changes.contents.forEach(function (newContent) { - if (content.name !== newContent.name) { - return; - } - - var newContentDesc = newContent.application; - var newSSRCs = newContentDesc.sources || []; - - ssrcs = ssrcs.concat(newSSRCs); - newDesc.contents[idx].application.sources = JSON.parse(JSON.stringify(ssrcs)); - - var newGroups = newContentDesc.sourceGroups || []; - groups = groups.concat(newGroups); - newDesc.contents[idx].application.sourceGroups = JSON.parse(JSON.stringify(groups)); - }); - }); - - this.pc.handleOffer({ - type: 'offer', - jingle: newDesc - }, function (err) { - if (err) { - self._log('error', 'Error adding new stream source'); - return cb({ - condition: 'general-error' - }); - } - - self.pc.answer(function (err) { - if (err) { - self._log('error', 'Error adding new stream source'); - return cb({ - condition: 'general-error' - }); - } - cb(); - }); - }); - }, - - onSourceRemove: function (changes, cb) { - var self = this; - this._log('info', 'Removing stream source'); - - var newDesc = this.pc.remoteDescription; - this.pc.remoteDescription.contents.forEach(function (content, idx) { - var desc = content.application; - var ssrcs = desc.sources || []; - var groups = desc.sourceGroups || []; - - changes.contents.forEach(function (newContent) { - if (content.name !== newContent.name) { - return; - } - - var newContentDesc = newContent.application; - var newSSRCs = newContentDesc.sources || []; - var newGroups = newContentDesc.sourceGroups || []; - - var found, i, j, k; - - - for (i = 0; i < newSSRCs.length; i++) { - found = -1; - for (j = 0; j < ssrcs.length; j++) { - if (newSSRCs[i].ssrc === ssrcs[j].ssrc) { - found = j; - break; - } - } - if (found > -1) { - ssrcs.splice(found, 1); - newDesc.contents[idx].application.sources = JSON.parse(JSON.stringify(ssrcs)); - } - } - - // Remove ssrc-groups that are no longer needed - for (i = 0; i < newGroups.length; i++) { - found = -1; - for (j = 0; j < groups.length; j++) { - if (newGroups[i].semantics === groups[j].semantics && - newGroups[i].sources.length === groups[j].sources.length) { - var same = true; - for (k = 0; k < newGroups[i].sources.length; k++) { - if (newGroups[i].sources[k] !== groups[j].sources[k]) { - same = false; - break; - } - } - if (same) { - found = j; - break; - } - } - } - if (found > -1) { - groups.splice(found, 1); - newDesc.contents[idx].application.sourceGroups = JSON.parse(JSON.stringify(groups)); - } - } - }); - }); - - this.pc.handleOffer({ - type: 'offer', - jingle: newDesc - }, function (err) { - if (err) { - self._log('error', 'Error removing stream source'); - return cb({ - condition: 'general-error' - }); - } - self.pc.answer(function (err) { - if (err) { - self._log('error', 'Error removing stream source'); - return cb({ - condition: 'general-error' - }); - } - cb(); - }); - }); - }, - - // ---------------------------------------------------------------- - // DataChannels - // ---------------------------------------------------------------- - onAddChannel: function (channel) { - this.emit('addChannel', channel); - } -}); - - -module.exports = MediaSession; - -},{"extend-object":28,"jingle-session":51,"rtcpeerconnection":178,"util":208}],51:[function(require,module,exports){ -var util = require('util'); -var uuid = require('uuid'); -var async = require('async'); -var extend = require('extend-object'); -var WildEmitter = require('wildemitter'); - - -var ACTIONS = { - 'content-accept': 'onContentAccept', - 'content-add': 'onContentAdd', - 'content-modify': 'onConentModify', - 'content-reject': 'onContentReject', - 'content-remove': 'onContentRemove', - 'description-info': 'onDescriptionInfo', - 'security-info': 'onSecurityInfo', - 'session-accept': 'onSessionAccept', - 'session-info': 'onSessionInfo', - 'session-initiate': 'onSessionInitiate', - 'session-terminate': 'onSessionTerminate', - 'transport-accept': 'onTransportAccept', - 'transport-info': 'onTransportInfo', - 'transport-reject': 'onTransportReject', - 'transport-replace': 'onTransportReplace', - - // Unstandardized actions: might go away anytime without notice - 'source-add': 'onSourceAdd', - 'source-remove': 'onSourceRemove' -}; - - -function JingleSession(opts) { - WildEmitter.call(this); - - var self = this; - - this.sid = opts.sid || uuid.v4(); - this.peer = opts.peer; - this.peerID = opts.peerID || this.peer.full || this.peer; - this.isInitiator = opts.initiator || false; - this.parent = opts.parent; - this.state = 'starting'; - this.connectionState = 'starting'; - - // We track the intial pending description types in case - // of the need for a tie-breaker. - this.pendingApplicationTypes = opts.applicationTypes || []; - - this.pendingAction = false; - - // Here is where we'll ensure that all actions are processed - // in order, even if a particular action requires async handling. - this.processingQueue = async.queue(function (task, next) { - if (self.ended) { - // Don't process anything once the session has been ended - return next(); - } - - var action = task.action; - var changes = task.changes; - var cb = task.cb; - - self._log('debug', action); - - if (!ACTIONS[action]) { - self._log('error', 'Invalid action: ' + action); - cb({condition: 'bad-request'}); - return next(); - } - - self[ACTIONS[action]](changes, function (err, result) { - cb(err, result); - return next(); - }); - }); -} - - -util.inherits(JingleSession, WildEmitter); - -// We don't know how to handle any particular content types, -// so no actions are supported. -Object.keys(ACTIONS).forEach(function (action) { - var method = ACTIONS[action]; - JingleSession.prototype[method] = function (changes, cb) { - this._log('error', 'Unsupported action: ' + action); - cb(); - }; -}); - -// Provide some convenience properties for checking -// the session's state. -Object.defineProperties(JingleSession.prototype, { - state: { - get: function () { - return this._sessionState; - }, - set: function (value) { - if (value !== this._sessionState) { - var prev = this._sessionState; - this._log('info', 'Changing session state to: ' + value); - this._sessionState = value; - this.emit('change:sessionState', this, value); - this.emit('change:' + value, this, true); - if (prev) { - this.emit('change:' + prev, this, false); - } - } - } - }, - connectionState: { - get: function () { - return this._connectionState; - }, - set: function (value) { - if (value !== this._connectionState) { - var prev = this._connectionState; - this._log('info', 'Changing connection state to: ' + value); - this._connectionState = value; - this.emit('change:connectionState', this, value); - this.emit('change:' + value, this, true); - if (prev) { - this.emit('change:' + prev, this, false); - } - } - } - }, - starting: { - get: function () { - return this._sessionState === 'starting'; - } - }, - pending: { - get: function () { - return this._sessionState === 'pending'; - } - }, - active: { - get: function () { - return this._sessionState === 'active'; - } - }, - ended: { - get: function () { - return this._sessionState === 'ended'; - } - }, - connected: { - get: function () { - return this._connectionState === 'connected'; - } - }, - connecting: { - get: function () { - return this._connectionState === 'connecting'; - } - }, - disconnected: { - get: function () { - return this._connectionState === 'disconnected'; - } - }, - interrupted: { - get: function () { - return this._connectionState === 'interrupted'; - } - } -}); - -JingleSession.prototype = extend(JingleSession.prototype, { - _log: function (level, message) { - message = this.sid + ': ' + message; - this.emit('log:' + level, message); - }, - - send: function (action, data) { - data = data || {}; - data.sid = this.sid; - data.action = action; - - var requirePending = { - 'session-inititate': true, - 'session-accept': true, - 'content-add': true, - 'content-remove': true, - 'content-reject': true, - 'content-accept': true, - 'content-modify': true, - 'transport-replace': true, - 'transport-reject': true, - 'transport-accept': true, - 'source-add': true, - 'source-remove': true - }; - - if (requirePending[action]) { - this.pendingAction = action; - } else { - this.pendingAction = false; - } - - this.emit('send', { - to: this.peer, - type: 'set', - jingle: data - }); - }, - - process: function (action, changes, cb) { - this.processingQueue.push({ - action: action, - changes: changes, - cb: cb - }); - }, - - start: function () { - this._log('error', 'Can not start base sessions'); - this.end('unsupported-applications', true); - }, - - accept: function () { - this._log('error', 'Can not accept base sessions'); - this.end('unsupported-applications'); - }, - - cancel: function () { - this.end('cancel'); - }, - - decline: function () { - this.end('decline'); - }, - - end: function (reason, silent) { - this.state = 'ended'; - - this.processingQueue.kill(); - - if (!reason) { - reason = 'success'; - } - - if (typeof reason === 'string') { - reason = { - condition: reason - }; - } - - if (!silent) { - this.send('session-terminate', { - reason: reason - }); - } - - this.emit('terminated', this, reason); - }, - - onSessionTerminate: function (changes, cb) { - this.end(changes.reason, true); - cb(); - }, - - // It is mandatory to reply to a session-info action with - // an unsupported-info error if the info isn't recognized. - // - // However, a session-info action with no associated payload - // is acceptable (works like a ping). - onSessionInfo: function (changes, cb) { - var okKeys = { - sid: true, - action: true, - initiator: true, - responder: true - }; - - var unknownPayload = false; - Object.keys(changes).forEach(function (key) { - if (!okKeys[key]) { - unknownPayload = true; - } - }); - - if (unknownPayload) { - cb({ - type: 'modify', - condition: 'feature-not-implemented', - jingleCondition: 'unsupported-info' - }); - } else { - cb(); - } - }, - - // It is mandatory to reply to a description-info action with - // an unsupported-info error if the info isn't recognized. - onDescriptionInfo: function (changes, cb) { - cb({ - type: 'modify', - condition: 'feature-not-implemented', - jingleCondition: 'unsupported-info' - }); - }, - - // It is mandatory to reply to a transport-info action with - // an unsupported-info error if the info isn't recognized. - onTransportInfo: function (changes, cb) { - cb({ - type: 'modify', - condition: 'feature-not-implemented', - jingleCondition: 'unsupported-info' - }); - }, - - // It is mandatory to reply to a content-add action with either - // a content-accept or content-reject. - onContentAdd: function (changes, cb) { - // Allow ack for the content-add to be sent. - cb(); - - this.send('content-reject', { - reason: { - condition: 'failed-application', - text: 'content-add is not supported' - } - }); - }, - - // It is mandatory to reply to a transport-add action with either - // a transport-accept or transport-reject. - onTransportReplace: function (changes, cb) { - // Allow ack for the transport-replace be sent. - cb(); - - this.send('transport-reject', { - reason: { - condition: 'failed-application', - text: 'transport-replace is not supported' - } - }); - } -}); - - -module.exports = JingleSession; - -},{"async":52,"extend-object":28,"util":208,"uuid":210,"wildemitter":223}],52:[function(require,module,exports){ -(function (process,global){ -/*! - * async - * https://github.com/caolan/async - * - * Copyright 2010-2014 Caolan McMahon - * Released under the MIT license - */ -(function () { - - var async = {}; - function noop() {} - function identity(v) { - return v; - } - function toBool(v) { - return !!v; - } - function notId(v) { - return !v; - } - - // global on the server, window in the browser - var previous_async; - - // Establish the root object, `window` (`self`) in the browser, `global` - // on the server, or `this` in some virtual machines. We use `self` - // instead of `window` for `WebWorker` support. - var root = typeof self === 'object' && self.self === self && self || - typeof global === 'object' && global.global === global && global || - this; - - if (root != null) { - previous_async = root.async; - } - - async.noConflict = function () { - root.async = previous_async; - return async; - }; - - function only_once(fn) { - return function() { - if (fn === null) throw new Error("Callback was already called."); - fn.apply(this, arguments); - fn = null; - }; - } - - function _once(fn) { - return function() { - if (fn === null) return; - fn.apply(this, arguments); - fn = null; - }; - } - - //// cross-browser compatiblity functions //// - - var _toString = Object.prototype.toString; - - var _isArray = Array.isArray || function (obj) { - return _toString.call(obj) === '[object Array]'; - }; - - // Ported from underscore.js isObject - var _isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - function _isArrayLike(arr) { - return _isArray(arr) || ( - // has a positive integer length property - typeof arr.length === "number" && - arr.length >= 0 && - arr.length % 1 === 0 - ); - } - - function _arrayEach(arr, iterator) { - var index = -1, - length = arr.length; - - while (++index < length) { - iterator(arr[index], index, arr); - } - } - - function _map(arr, iterator) { - var index = -1, - length = arr.length, - result = Array(length); - - while (++index < length) { - result[index] = iterator(arr[index], index, arr); - } - return result; - } - - function _range(count) { - return _map(Array(count), function (v, i) { return i; }); - } - - function _reduce(arr, iterator, memo) { - _arrayEach(arr, function (x, i, a) { - memo = iterator(memo, x, i, a); - }); - return memo; - } - - function _forEachOf(object, iterator) { - _arrayEach(_keys(object), function (key) { - iterator(object[key], key); - }); - } - - function _indexOf(arr, item) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] === item) return i; - } - return -1; - } - - var _keys = Object.keys || function (obj) { - var keys = []; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - keys.push(k); - } - } - return keys; - }; - - function _keyIterator(coll) { - var i = -1; - var len; - var keys; - if (_isArrayLike(coll)) { - len = coll.length; - return function next() { - i++; - return i < len ? i : null; - }; - } else { - keys = _keys(coll); - len = keys.length; - return function next() { - i++; - return i < len ? keys[i] : null; - }; - } - } - - // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) - // This accumulates the arguments passed into an array, after a given index. - // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). - function _restParam(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0); - var rest = Array(length); - for (var index = 0; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - } - // Currently unused but handle cases outside of the switch statement: - // var args = Array(startIndex + 1); - // for (index = 0; index < startIndex; index++) { - // args[index] = arguments[index]; - // } - // args[startIndex] = rest; - // return func.apply(this, args); - }; - } - - function _withoutIndex(iterator) { - return function (value, index, callback) { - return iterator(value, callback); - }; - } - - //// exported async module functions //// - - //// nextTick implementation with browser-compatible fallback //// - - // capture the global reference to guard against fakeTimer mocks - var _setImmediate = typeof setImmediate === 'function' && setImmediate; - - var _delay = _setImmediate ? function(fn) { - // not a direct alias for IE10 compatibility - _setImmediate(fn); - } : function(fn) { - setTimeout(fn, 0); - }; - - if (typeof process === 'object' && typeof process.nextTick === 'function') { - async.nextTick = process.nextTick; - } else { - async.nextTick = _delay; - } - async.setImmediate = _setImmediate ? _delay : async.nextTick; - - - async.forEach = - async.each = function (arr, iterator, callback) { - return async.eachOf(arr, _withoutIndex(iterator), callback); - }; - - async.forEachSeries = - async.eachSeries = function (arr, iterator, callback) { - return async.eachOfSeries(arr, _withoutIndex(iterator), callback); - }; - - - async.forEachLimit = - async.eachLimit = function (arr, limit, iterator, callback) { - return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); - }; - - async.forEachOf = - async.eachOf = function (object, iterator, callback) { - callback = _once(callback || noop); - object = object || []; - - var iter = _keyIterator(object); - var key, completed = 0; - - while ((key = iter()) != null) { - completed += 1; - iterator(object[key], key, only_once(done)); - } - - if (completed === 0) callback(null); - - function done(err) { - completed--; - if (err) { - callback(err); - } - // Check key is null in case iterator isn't exhausted - // and done resolved synchronously. - else if (key === null && completed <= 0) { - callback(null); - } - } - }; - - async.forEachOfSeries = - async.eachOfSeries = function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - var key = nextKey(); - function iterate() { - var sync = true; - if (key === null) { - return callback(null); - } - iterator(obj[key], key, only_once(function (err) { - if (err) { - callback(err); - } - else { - key = nextKey(); - if (key === null) { - return callback(null); - } else { - if (sync) { - async.setImmediate(iterate); - } else { - iterate(); - } - } - } - })); - sync = false; - } - iterate(); - }; - - - - async.forEachOfLimit = - async.eachOfLimit = function (obj, limit, iterator, callback) { - _eachOfLimit(limit)(obj, iterator, callback); - }; - - function _eachOfLimit(limit) { - - return function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - if (limit <= 0) { - return callback(null); - } - var done = false; - var running = 0; - var errored = false; - - (function replenish () { - if (done && running <= 0) { - return callback(null); - } - - while (running < limit && !errored) { - var key = nextKey(); - if (key === null) { - done = true; - if (running <= 0) { - callback(null); - } - return; - } - running += 1; - iterator(obj[key], key, only_once(function (err) { - running -= 1; - if (err) { - callback(err); - errored = true; - } - else { - replenish(); - } - })); - } - })(); - }; - } - - - function doParallel(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOf, obj, iterator, callback); - }; - } - function doParallelLimit(fn) { - return function (obj, limit, iterator, callback) { - return fn(_eachOfLimit(limit), obj, iterator, callback); - }; - } - function doSeries(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOfSeries, obj, iterator, callback); - }; - } - - function _asyncMap(eachfn, arr, iterator, callback) { - callback = _once(callback || noop); - arr = arr || []; - var results = _isArrayLike(arr) ? [] : {}; - eachfn(arr, function (value, index, callback) { - iterator(value, function (err, v) { - results[index] = v; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } - - async.map = doParallel(_asyncMap); - async.mapSeries = doSeries(_asyncMap); - async.mapLimit = doParallelLimit(_asyncMap); - - // reduce only has a series version, as doing reduce in parallel won't - // work in many situations. - async.inject = - async.foldl = - async.reduce = function (arr, memo, iterator, callback) { - async.eachOfSeries(arr, function (x, i, callback) { - iterator(memo, x, function (err, v) { - memo = v; - callback(err); - }); - }, function (err) { - callback(err, memo); - }); - }; - - async.foldr = - async.reduceRight = function (arr, memo, iterator, callback) { - var reversed = _map(arr, identity).reverse(); - async.reduce(reversed, memo, iterator, callback); - }; - - async.transform = function (arr, memo, iterator, callback) { - if (arguments.length === 3) { - callback = iterator; - iterator = memo; - memo = _isArray(arr) ? [] : {}; - } - - async.eachOf(arr, function(v, k, cb) { - iterator(memo, v, k, cb); - }, function(err) { - callback(err, memo); - }); - }; - - function _filter(eachfn, arr, iterator, callback) { - var results = []; - eachfn(arr, function (x, index, callback) { - iterator(x, function (v) { - if (v) { - results.push({index: index, value: x}); - } - callback(); - }); - }, function () { - callback(_map(results.sort(function (a, b) { - return a.index - b.index; - }), function (x) { - return x.value; - })); - }); - } - - async.select = - async.filter = doParallel(_filter); - - async.selectLimit = - async.filterLimit = doParallelLimit(_filter); - - async.selectSeries = - async.filterSeries = doSeries(_filter); - - function _reject(eachfn, arr, iterator, callback) { - _filter(eachfn, arr, function(value, cb) { - iterator(value, function(v) { - cb(!v); - }); - }, callback); - } - async.reject = doParallel(_reject); - async.rejectLimit = doParallelLimit(_reject); - async.rejectSeries = doSeries(_reject); - - function _createTester(eachfn, check, getResult) { - return function(arr, limit, iterator, cb) { - function done() { - if (cb) cb(getResult(false, void 0)); - } - function iteratee(x, _, callback) { - if (!cb) return callback(); - iterator(x, function (v) { - if (cb && check(v)) { - cb(getResult(true, x)); - cb = iterator = false; - } - callback(); - }); - } - if (arguments.length > 3) { - eachfn(arr, limit, iteratee, done); - } else { - cb = iterator; - iterator = limit; - eachfn(arr, iteratee, done); - } - }; - } - - async.any = - async.some = _createTester(async.eachOf, toBool, identity); - - async.someLimit = _createTester(async.eachOfLimit, toBool, identity); - - async.all = - async.every = _createTester(async.eachOf, notId, notId); - - async.everyLimit = _createTester(async.eachOfLimit, notId, notId); - - function _findGetResult(v, x) { - return x; - } - async.detect = _createTester(async.eachOf, identity, _findGetResult); - async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); - async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult); - - async.sortBy = function (arr, iterator, callback) { - async.map(arr, function (x, callback) { - iterator(x, function (err, criteria) { - if (err) { - callback(err); - } - else { - callback(null, {value: x, criteria: criteria}); - } - }); - }, function (err, results) { - if (err) { - return callback(err); - } - else { - callback(null, _map(results.sort(comparator), function (x) { - return x.value; - })); - } - - }); - - function comparator(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - } - }; - - async.auto = function (tasks, concurrency, callback) { - if (typeof arguments[1] === 'function') { - // concurrency is optional, shift the args. - callback = concurrency; - concurrency = null; - } - callback = _once(callback || noop); - var keys = _keys(tasks); - var remainingTasks = keys.length; - if (!remainingTasks) { - return callback(null); - } - if (!concurrency) { - concurrency = remainingTasks; - } - - var results = {}; - var runningTasks = 0; - - var hasError = false; - - var listeners = []; - function addListener(fn) { - listeners.unshift(fn); - } - function removeListener(fn) { - var idx = _indexOf(listeners, fn); - if (idx >= 0) listeners.splice(idx, 1); - } - function taskComplete() { - remainingTasks--; - _arrayEach(listeners.slice(0), function (fn) { - fn(); - }); - } - - addListener(function () { - if (!remainingTasks) { - callback(null, results); - } - }); - - _arrayEach(keys, function (k) { - if (hasError) return; - var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; - var taskCallback = _restParam(function(err, args) { - runningTasks--; - if (args.length <= 1) { - args = args[0]; - } - if (err) { - var safeResults = {}; - _forEachOf(results, function(val, rkey) { - safeResults[rkey] = val; - }); - safeResults[k] = args; - hasError = true; - - callback(err, safeResults); - } - else { - results[k] = args; - async.setImmediate(taskComplete); - } - }); - var requires = task.slice(0, task.length - 1); - // prevent dead-locks - var len = requires.length; - var dep; - while (len--) { - if (!(dep = tasks[requires[len]])) { - throw new Error('Has nonexistent dependency in ' + requires.join(', ')); - } - if (_isArray(dep) && _indexOf(dep, k) >= 0) { - throw new Error('Has cyclic dependencies'); - } - } - function ready() { - return runningTasks < concurrency && _reduce(requires, function (a, x) { - return (a && results.hasOwnProperty(x)); - }, true) && !results.hasOwnProperty(k); - } - if (ready()) { - runningTasks++; - task[task.length - 1](taskCallback, results); - } - else { - addListener(listener); - } - function listener() { - if (ready()) { - runningTasks++; - removeListener(listener); - task[task.length - 1](taskCallback, results); - } - } - }); - }; - - - - async.retry = function(times, task, callback) { - var DEFAULT_TIMES = 5; - var DEFAULT_INTERVAL = 0; - - var attempts = []; - - var opts = { - times: DEFAULT_TIMES, - interval: DEFAULT_INTERVAL - }; - - function parseTimes(acc, t){ - if(typeof t === 'number'){ - acc.times = parseInt(t, 10) || DEFAULT_TIMES; - } else if(typeof t === 'object'){ - acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; - acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; - } else { - throw new Error('Unsupported argument type for \'times\': ' + typeof t); - } - } - - var length = arguments.length; - if (length < 1 || length > 3) { - throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); - } else if (length <= 2 && typeof times === 'function') { - callback = task; - task = times; - } - if (typeof times !== 'function') { - parseTimes(opts, times); - } - opts.callback = callback; - opts.task = task; - - function wrappedTask(wrappedCallback, wrappedResults) { - function retryAttempt(task, finalAttempt) { - return function(seriesCallback) { - task(function(err, result){ - seriesCallback(!err || finalAttempt, {err: err, result: result}); - }, wrappedResults); - }; - } - - function retryInterval(interval){ - return function(seriesCallback){ - setTimeout(function(){ - seriesCallback(null); - }, interval); - }; - } - - while (opts.times) { - - var finalAttempt = !(opts.times-=1); - attempts.push(retryAttempt(opts.task, finalAttempt)); - if(!finalAttempt && opts.interval > 0){ - attempts.push(retryInterval(opts.interval)); - } - } - - async.series(attempts, function(done, data){ - data = data[data.length - 1]; - (wrappedCallback || opts.callback)(data.err, data.result); - }); - } - - // If a callback is passed, run this as a controll flow - return opts.callback ? wrappedTask() : wrappedTask; - }; - - async.waterfall = function (tasks, callback) { - callback = _once(callback || noop); - if (!_isArray(tasks)) { - var err = new Error('First argument to waterfall must be an array of functions'); - return callback(err); - } - if (!tasks.length) { - return callback(); - } - function wrapIterator(iterator) { - return _restParam(function (err, args) { - if (err) { - callback.apply(null, [err].concat(args)); - } - else { - var next = iterator.next(); - if (next) { - args.push(wrapIterator(next)); - } - else { - args.push(callback); - } - ensureAsync(iterator).apply(null, args); - } - }); - } - wrapIterator(async.iterator(tasks))(); - }; - - function _parallel(eachfn, tasks, callback) { - callback = callback || noop; - var results = _isArrayLike(tasks) ? [] : {}; - - eachfn(tasks, function (task, key, callback) { - task(_restParam(function (err, args) { - if (args.length <= 1) { - args = args[0]; - } - results[key] = args; - callback(err); - })); - }, function (err) { - callback(err, results); - }); - } - - async.parallel = function (tasks, callback) { - _parallel(async.eachOf, tasks, callback); - }; - - async.parallelLimit = function(tasks, limit, callback) { - _parallel(_eachOfLimit(limit), tasks, callback); - }; - - async.series = function(tasks, callback) { - _parallel(async.eachOfSeries, tasks, callback); - }; - - async.iterator = function (tasks) { - function makeCallback(index) { - function fn() { - if (tasks.length) { - tasks[index].apply(null, arguments); - } - return fn.next(); - } - fn.next = function () { - return (index < tasks.length - 1) ? makeCallback(index + 1): null; - }; - return fn; - } - return makeCallback(0); - }; - - async.apply = _restParam(function (fn, args) { - return _restParam(function (callArgs) { - return fn.apply( - null, args.concat(callArgs) - ); - }); - }); - - function _concat(eachfn, arr, fn, callback) { - var result = []; - eachfn(arr, function (x, index, cb) { - fn(x, function (err, y) { - result = result.concat(y || []); - cb(err); - }); - }, function (err) { - callback(err, result); - }); - } - async.concat = doParallel(_concat); - async.concatSeries = doSeries(_concat); - - async.whilst = function (test, iterator, callback) { - callback = callback || noop; - if (test()) { - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else if (test.apply(this, args)) { - iterator(next); - } else { - callback.apply(null, [null].concat(args)); - } - }); - iterator(next); - } else { - callback(null); - } - }; - - async.doWhilst = function (iterator, test, callback) { - var calls = 0; - return async.whilst(function() { - return ++calls <= 1 || test.apply(this, arguments); - }, iterator, callback); - }; - - async.until = function (test, iterator, callback) { - return async.whilst(function() { - return !test.apply(this, arguments); - }, iterator, callback); - }; - - async.doUntil = function (iterator, test, callback) { - return async.doWhilst(iterator, function() { - return !test.apply(this, arguments); - }, callback); - }; - - async.during = function (test, iterator, callback) { - callback = callback || noop; - - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else { - args.push(check); - test.apply(this, args); - } - }); - - var check = function(err, truth) { - if (err) { - callback(err); - } else if (truth) { - iterator(next); - } else { - callback(null); - } - }; - - test(check); - }; - - async.doDuring = function (iterator, test, callback) { - var calls = 0; - async.during(function(next) { - if (calls++ < 1) { - next(null, true); - } else { - test.apply(this, arguments); - } - }, iterator, callback); - }; - - function _queue(worker, concurrency, payload) { - if (concurrency == null) { - concurrency = 1; - } - else if(concurrency === 0) { - throw new Error('Concurrency must not be zero'); - } - function _insert(q, data, pos, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0 && q.idle()) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - callback: callback || noop - }; - - if (pos) { - q.tasks.unshift(item); - } else { - q.tasks.push(item); - } - - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - }); - async.setImmediate(q.process); - } - function _next(q, tasks) { - return function(){ - workers -= 1; - - var removed = false; - var args = arguments; - _arrayEach(tasks, function (task) { - _arrayEach(workersList, function (worker, index) { - if (worker === task && !removed) { - workersList.splice(index, 1); - removed = true; - } - }); - - task.callback.apply(task, args); - }); - if (q.tasks.length + workers === 0) { - q.drain(); - } - q.process(); - }; - } - - var workers = 0; - var workersList = []; - var q = { - tasks: [], - concurrency: concurrency, - payload: payload, - saturated: noop, - empty: noop, - drain: noop, - started: false, - paused: false, - push: function (data, callback) { - _insert(q, data, false, callback); - }, - kill: function () { - q.drain = noop; - q.tasks = []; - }, - unshift: function (data, callback) { - _insert(q, data, true, callback); - }, - process: function () { - while(!q.paused && workers < q.concurrency && q.tasks.length){ - - var tasks = q.payload ? - q.tasks.splice(0, q.payload) : - q.tasks.splice(0, q.tasks.length); - - var data = _map(tasks, function (task) { - return task.data; - }); - - if (q.tasks.length === 0) { - q.empty(); - } - workers += 1; - workersList.push(tasks[0]); - var cb = only_once(_next(q, tasks)); - worker(data, cb); - } - }, - length: function () { - return q.tasks.length; - }, - running: function () { - return workers; - }, - workersList: function () { - return workersList; - }, - idle: function() { - return q.tasks.length + workers === 0; - }, - pause: function () { - q.paused = true; - }, - resume: function () { - if (q.paused === false) { return; } - q.paused = false; - var resumeCount = Math.min(q.concurrency, q.tasks.length); - // Need to call q.process once per concurrent - // worker to preserve full concurrency after pause - for (var w = 1; w <= resumeCount; w++) { - async.setImmediate(q.process); - } - } - }; - return q; - } - - async.queue = function (worker, concurrency) { - var q = _queue(function (items, cb) { - worker(items[0], cb); - }, concurrency, 1); - - return q; - }; - - async.priorityQueue = function (worker, concurrency) { - - function _compareTasks(a, b){ - return a.priority - b.priority; - } - - function _binarySearch(sequence, item, compare) { - var beg = -1, - end = sequence.length - 1; - while (beg < end) { - var mid = beg + ((end - beg + 1) >>> 1); - if (compare(item, sequence[mid]) >= 0) { - beg = mid; - } else { - end = mid - 1; - } - } - return beg; - } - - function _insert(q, data, priority, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - priority: priority, - callback: typeof callback === 'function' ? callback : noop - }; - - q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); - - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); - } - - // Start with a normal queue - var q = async.queue(worker, concurrency); - - // Override push to accept second parameter representing priority - q.push = function (data, priority, callback) { - _insert(q, data, priority, callback); - }; - - // Remove unshift function - delete q.unshift; - - return q; - }; - - async.cargo = function (worker, payload) { - return _queue(worker, 1, payload); - }; - - function _console_fn(name) { - return _restParam(function (fn, args) { - fn.apply(null, args.concat([_restParam(function (err, args) { - if (typeof console === 'object') { - if (err) { - if (console.error) { - console.error(err); - } - } - else if (console[name]) { - _arrayEach(args, function (x) { - console[name](x); - }); - } - } - })])); - }); - } - async.log = _console_fn('log'); - async.dir = _console_fn('dir'); - /*async.info = _console_fn('info'); - async.warn = _console_fn('warn'); - async.error = _console_fn('error');*/ - - async.memoize = function (fn, hasher) { - var memo = {}; - var queues = {}; - var has = Object.prototype.hasOwnProperty; - hasher = hasher || identity; - var memoized = _restParam(function memoized(args) { - var callback = args.pop(); - var key = hasher.apply(null, args); - if (has.call(memo, key)) { - async.setImmediate(function () { - callback.apply(null, memo[key]); - }); - } - else if (has.call(queues, key)) { - queues[key].push(callback); - } - else { - queues[key] = [callback]; - fn.apply(null, args.concat([_restParam(function (args) { - memo[key] = args; - var q = queues[key]; - delete queues[key]; - for (var i = 0, l = q.length; i < l; i++) { - q[i].apply(null, args); - } - })])); - } - }); - memoized.memo = memo; - memoized.unmemoized = fn; - return memoized; - }; - - async.unmemoize = function (fn) { - return function () { - return (fn.unmemoized || fn).apply(null, arguments); - }; - }; - - function _times(mapper) { - return function (count, iterator, callback) { - mapper(_range(count), iterator, callback); - }; - } - - async.times = _times(async.map); - async.timesSeries = _times(async.mapSeries); - async.timesLimit = function (count, limit, iterator, callback) { - return async.mapLimit(_range(count), limit, iterator, callback); - }; - - async.seq = function (/* functions... */) { - var fns = arguments; - return _restParam(function (args) { - var that = this; - - var callback = args[args.length - 1]; - if (typeof callback == 'function') { - args.pop(); - } else { - callback = noop; - } - - async.reduce(fns, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { - cb(err, nextargs); - })])); - }, - function (err, results) { - callback.apply(that, [err].concat(results)); - }); - }); - }; - - async.compose = function (/* functions... */) { - return async.seq.apply(null, Array.prototype.reverse.call(arguments)); - }; - - - function _applyEach(eachfn) { - return _restParam(function(fns, args) { - var go = _restParam(function(args) { - var that = this; - var callback = args.pop(); - return eachfn(fns, function (fn, _, cb) { - fn.apply(that, args.concat([cb])); - }, - callback); - }); - if (args.length) { - return go.apply(this, args); - } - else { - return go; - } - }); - } - - async.applyEach = _applyEach(async.eachOf); - async.applyEachSeries = _applyEach(async.eachOfSeries); - - - async.forever = function (fn, callback) { - var done = only_once(callback || noop); - var task = ensureAsync(fn); - function next(err) { - if (err) { - return done(err); - } - task(next); - } - next(); - }; - - function ensureAsync(fn) { - return _restParam(function (args) { - var callback = args.pop(); - args.push(function () { - var innerArgs = arguments; - if (sync) { - async.setImmediate(function () { - callback.apply(null, innerArgs); - }); - } else { - callback.apply(null, innerArgs); - } - }); - var sync = true; - fn.apply(this, args); - sync = false; - }); - } - - async.ensureAsync = ensureAsync; - - async.constant = _restParam(function(values) { - var args = [null].concat(values); - return function (callback) { - return callback.apply(this, args); - }; - }); - - async.wrapSync = - async.asyncify = function asyncify(func) { - return _restParam(function (args) { - var callback = args.pop(); - var result; - try { - result = func.apply(this, args); - } catch (e) { - return callback(e); - } - // if result is Promise object - if (_isObject(result) && typeof result.then === "function") { - result.then(function(value) { - callback(null, value); - })["catch"](function(err) { - callback(err.message ? err : new Error(err)); - }); - } else { - callback(null, result); - } - }); - }; - - // Node.js - if (typeof module === 'object' && module.exports) { - module.exports = async; - } - // AMD / RequireJS - else if (typeof define === 'function' && define.amd) { - define([], function () { - return async; - }); - } - // included directly via