New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

protoo-client

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

protoo-client - npm Package Compare versions

Comparing version

to
4.0.0

lib/EnhancedEventEmitter.js

2

.eslintrc.js

@@ -70,3 +70,3 @@ module.exports =

tabWidth: 2,
comments: 110,
comments: 100,
ignoreUrls: true,

@@ -73,0 +73,0 @@ ignoreStrings: true,

@@ -0,15 +1,24 @@

const { version } = require('../package.json');
const Peer = require('./Peer');
const transports = require('./transports');
const WebSocketTransport = require('./transports/WebSocketTransport');
module.exports =
{
/**
* Expose Peer.
*/
Peer : Peer,
/**
* Expose mediasoup-client version.
*
* @type {String}
*/
exports.version = version;
/**
* Expose the built-in WebSocketTransport.
*/
WebSocketTransport : transports.WebSocketTransport
};
/**
* Expose Peer class.
*
* @type {Class}
*/
exports.Peer = Peer;
/**
* Expose WebSocketTransport class.
*
* @type {Class}
*/
exports.WebSocketTransport = WebSocketTransport;

@@ -1,4 +0,6 @@

const logger = require('./logger')('Message');
const utils = require('./utils');
const Logger = require('./Logger');
const { generateRandomNumber } = require('./utils');
const logger = new Logger('Message');
class Message

@@ -49,3 +51,2 @@ {

message.id = object.id;
message.method = object.method;

@@ -77,2 +78,3 @@ message.data = object.data || {};

{
message.ok = false;
message.errorCode = object.errorCode;

@@ -108,3 +110,3 @@ message.errorReason = object.errorReason;

static requestFactory(method, data)
static createRequest(method, data)
{

@@ -114,3 +116,3 @@ const request =

request : true,
id : utils.randomNumber(),
id : generateRandomNumber(),
method : method,

@@ -123,3 +125,3 @@ data : data || {}

static successResponseFactory(request, data)
static createSuccessResponse(request, data)
{

@@ -137,3 +139,3 @@ const response =

static errorResponseFactory(request, errorCode, errorReason)
static createErrorResponse(request, errorCode, errorReason)
{

@@ -144,2 +146,3 @@ const response =

id : request.id,
ok : false,
errorCode : errorCode,

@@ -152,3 +155,3 @@ errorReason : errorReason

static notificationFactory(method, data)
static createNotification(method, data)
{

@@ -155,0 +158,0 @@ const notification =

@@ -1,28 +0,44 @@

const EventEmitter = require('events').EventEmitter;
const logger = require('./logger')('Peer');
const Logger = require('./Logger');
const EnhancedEventEmitter = require('./EnhancedEventEmitter');
const Message = require('./Message');
// Max time waiting for a response.
const REQUEST_TIMEOUT = 20000;
const logger = new Logger('Peer');
class Peer extends EventEmitter
class Peer extends EnhancedEventEmitter
{
/**
* @param {protoo.Transport} transport
*
* @emits open
* @emits {currentAttempt: Number} failed
* @emits disconnected
* @emits close
* @emits {request: protoo.Request, accept: Function, reject: Function} request
* @emits {notification: protoo.Notification} notification
*/
constructor(transport)
{
super(logger);
logger.debug('constructor()');
super();
this.setMaxListeners(Infinity);
// Closed flag.
// @type {Boolean}
this._closed = false;
// Transport.
// @type {protoo.Transport}
this._transport = transport;
// Closed flag.
this._closed = false;
// Connected flag.
// @type {Boolean}
this._connected = false;
// Custom data object.
// @type {Object}
this._data = {};
// Map of sent requests' handlers indexed by request.id.
this._requestHandlers = new Map();
// Map of pending sent request objects indexed by request id.
// @type {Map<Number, Object>}
this._sents = new Map();

@@ -33,93 +49,144 @@ // Handle transport.

get data()
/**
* Whether the Peer is closed.
*
* @returns {Boolean}
*/
get closed()
{
return this._data;
return this._closed;
}
set data(obj)
/**
* Whether the Peer is connected.
*
* @returns {Boolean}
*/
get connected()
{
this._data = obj || {};
return this._connected;
}
get closed()
/**
* App custom data.
*
* @returns {Object}
*/
get data()
{
return this._closed;
return this._data;
}
send(method, data)
/**
* Invalid setter.
*/
set data(data) // eslint-disable-line no-unused-vars
{
const request = Message.requestFactory(method, data);
throw new Error('cannot override data object');
}
return this._transport.send(request)
.then(() =>
{
return new Promise((pResolve, pReject) =>
{
const handler =
{
resolve : (data2) =>
{
if (!this._requestHandlers.delete(request.id))
return;
/**
* Close this Peer and its Transport.
*/
close()
{
if (this._closed)
return;
clearTimeout(handler.timer);
pResolve(data2);
},
logger.debug('close()');
reject : (error) =>
{
if (!this._requestHandlers.delete(request.id))
return;
this._closed = true;
this._connected = false;
clearTimeout(handler.timer);
pReject(error);
},
// Close Transport.
this._transport.close();
timer : setTimeout(() =>
{
if (!this._requestHandlers.delete(request.id))
return;
// Close every pending sent.
for (const sent of this._sents.values())
{
sent.close();
}
pReject(new Error('request timeout'));
}, REQUEST_TIMEOUT),
close : () =>
{
clearTimeout(handler.timer);
pReject(new Error('peer closed'));
}
};
// Add handler stuff to the Map.
this._requestHandlers.set(request.id, handler);
});
});
// Emit 'close' event.
this.safeEmit('close');
}
notify(method, data)
/**
* Send a protoo request to the server-side Room.
*
* @param {String} method
* @param {Object} [data]
*
* @async
* @returns {Object} The response data Object if a success response is received.
*/
async request(method, data = undefined)
{
const notification = Message.notificationFactory(method, data);
const request = Message.createRequest(method, data);
return this._transport.send(notification);
}
this._logger.debug('request() [method:%s, id:%s]', method, request.id);
close()
{
logger.debug('close()');
// This may throw.
this._transport.send(request);
if (this._closed)
return;
return new Promise((pResolve, pReject) =>
{
const timeout = 1500 * (15 + (0.1 * this._sents.size));
const sent =
{
id : request.id,
method : request.method,
resolve : (data2) =>
{
if (!this._sents.delete(request.id))
return;
this._closed = true;
clearTimeout(sent.timer);
pResolve(data2);
},
reject : (error) =>
{
if (!this._sents.delete(request.id))
return;
// Close transport.
this._transport.close();
clearTimeout(sent.timer);
pReject(error);
},
timer : setTimeout(() =>
{
if (!this._sents.delete(request.id))
return;
// Close every pending request handler.
this._requestHandlers.forEach((handler) => handler.close());
pReject(new Error('request timeout'));
}, timeout),
close : () =>
{
clearTimeout(sent.timer);
pReject(new Error('peer closed'));
}
};
// Emit 'close' event.
this.emit('close');
// Add sent stuff to the map.
this._sents.set(request.id, sent);
});
}
/**
* Send a protoo notification to the server-side Room.
*
* @param {String} method
* @param {Object} [data]
*
* @async
*/
async notify(method, data = undefined)
{
const notification = Message.createNotification(method, data);
this._logger.debug('notify() [method:%s]', method);
// This may throw.
this._transport.send(notification);
}
_handleTransport()

@@ -130,14 +197,16 @@ {

this._closed = true;
setTimeout(() => this.emit('close'));
setTimeout(() =>
{
if (this._closed)
return;
this._connected = false;
this.safeEmit('close');
});
return;
}
this._transport.on('connecting', (currentAttempt) =>
{
logger.debug('emit "connecting" [currentAttempt:%s]', currentAttempt);
this.emit('connecting', currentAttempt);
});
this._transport.on('open', () =>

@@ -150,4 +219,5 @@ {

// Emit 'open' event.
this.emit('open');
this._connected = true;
this.safeEmit('open');
});

@@ -157,5 +227,10 @@

{
if (this._closed)
return;
logger.debug('emit "disconnected"');
this.emit('disconnected');
this._connected = false;
this.safeEmit('disconnected');
});

@@ -165,5 +240,10 @@

{
if (this._closed)
return;
logger.debug('emit "failed" [currentAttempt:%s]', currentAttempt);
this.emit('failed', currentAttempt);
this._connected = false;
this.safeEmit('failed', currentAttempt);
});

@@ -180,4 +260,5 @@

// Emit 'close' event.
this.emit('close');
this._connected = false;
this.safeEmit('close');
});

@@ -188,13 +269,7 @@

if (message.request)
{
this._handleRequest(message);
}
else if (message.response)
{
this._handleResponse(message);
}
else if (message.notification)
{
this._handleNotification(message);
}
});

@@ -205,40 +280,42 @@ }

{
this.emit('request',
// Request.
request,
// accept() function.
(data) =>
{
const response = Message.successResponseFactory(request, data);
try
{
this.emit('request',
// Request.
request,
// accept() function.
(data) =>
{
const response = Message.createSuccessResponse(request, data);
this._transport.send(response)
.catch((error) =>
this._transport.send(response)
.catch(() => {});
},
// reject() function.
(errorCode, errorReason) =>
{
if (errorCode instanceof Error)
{
logger.warn(
'accept() failed, response could not be sent: %o', error);
});
},
// reject() function.
(errorCode, errorReason) =>
{
if (errorCode instanceof Error)
{
errorReason = errorCode.toString();
errorCode = 500;
}
else if (typeof errorCode === 'number' && errorReason instanceof Error)
{
errorReason = errorReason.toString();
}
errorCode = 500;
errorReason = String(errorCode);
}
else if (typeof errorCode === 'number' && errorReason instanceof Error)
{
errorReason = String(errorReason);
}
const response =
Message.errorResponseFactory(request, errorCode, errorReason);
const response =
Message.createErrorResponse(request, errorCode, errorReason);
this._transport.send(response)
.catch((error) =>
{
logger.warn(
'reject() failed, response could not be sent: %o', error);
});
});
this._transport.send(response)
.catch(() => {});
});
}
catch (error)
{
const response = Message.createErrorResponse(request, 500, String(error));
this._transport.send(response)
.catch(() => {});
}
}

@@ -248,7 +325,8 @@

{
const handler = this._requestHandlers.get(response.id);
const sent = this._sents.get(response.id);
if (!handler)
if (!sent)
{
logger.error('received response does not match any sent request');
logger.error(
'received response does not match any sent request [id:%s]', response.id);

@@ -260,3 +338,3 @@ return;

{
handler.resolve(response.data);
sent.resolve(response.data);
}

@@ -268,3 +346,3 @@ else

error.code = response.errorCode;
handler.reject(error);
sent.reject(error);
}

@@ -275,3 +353,3 @@ }

{
this.emit('notification', notification);
this.safeEmit('notification', notification);
}

@@ -278,0 +356,0 @@ }

@@ -1,5 +0,5 @@

const EventEmitter = require('events').EventEmitter;
const W3CWebSocket = require('websocket').w3cwebsocket;
const retry = require('retry');
const logger = require('../logger')('WebSocketTransport');
const Logger = require('../Logger');
const EnhancedEventEmitter = require('../EnhancedEventEmitter');
const Message = require('../Message');

@@ -16,23 +16,34 @@

class WebSocketTransport extends EventEmitter
const logger = new Logger('WebSocketTransport');
class WebSocketTransport extends EnhancedEventEmitter
{
/**
* @param {String} url - WebSocket URL.
* @param {Object} [options] - Options for WebSocket-Node.W3CWebSocket and retry.
*/
constructor(url, options)
{
logger.debug('constructor() [url:"%s", options:%o]', url, options);
super(logger);
super();
this.setMaxListeners(Infinity);
logger.debug('constructor() [url:%s, options:%o]', url, options);
// Save URL and options.
// Closed flag.
// @type {Boolean}
this._closed = false;
// WebSocket URL.
// @type {String}
this._url = url;
// Options.
// @type {Object}
this._options = options || {};
// WebSocket instance.
// @type {WebSocket}
this._ws = null;
// Closed flag.
this._closed = false;
// Set WebSocket
this._setWebSocket();
// Run the WebSocket.
this._runWebSocket();
}

@@ -45,31 +56,12 @@

send(message)
close()
{
if (this._closed)
return Promise.reject(new Error('transport closed'));
return;
try
{
this._ws.send(JSON.stringify(message));
return Promise.resolve();
}
catch (error)
{
logger.error('send() | error sending message: %o', error);
return Promise.reject(error);
}
}
close()
{
logger.debug('close()');
if (this._closed)
return;
// Don't wait for the WebSocket 'close' event, do it now.
this._closed = true;
this.emit('close');
this.safeEmit('close');

@@ -90,6 +82,24 @@ try

_setWebSocket()
async send(message)
{
const options = this._options;
const operation = retry.operation(this._options.retry || DEFAULT_RETRY_OPTIONS);
if (this._closed)
throw new Error('transport closed');
try
{
this._ws.send(JSON.stringify(message));
}
catch (error)
{
logger.warn('send() failed:%o', error);
throw error;
}
}
_runWebSocket()
{
const operation =
retry.operation(this._options.retry || DEFAULT_RETRY_OPTIONS);
let wasConnected = false;

@@ -106,3 +116,3 @@

logger.debug('_setWebSocket() [currentAttempt:%s]', currentAttempt);
logger.debug('_runWebSocket() [currentAttempt:%s]', currentAttempt);

@@ -112,10 +122,7 @@ this._ws = new W3CWebSocket(

WS_SUBPROTOCOL,
options.origin,
options.headers,
options.requestOptions,
options.clientConfig
);
this._options.origin,
this._options.headers,
this._options.requestOptions,
this._options.clientConfig);
this.emit('connecting', currentAttempt);
this._ws.onopen = () =>

@@ -129,3 +136,3 @@ {

// Emit 'open' event.
this.emit('open');
this.safeEmit('open');
};

@@ -138,3 +145,4 @@

logger.warn('WebSocket "close" event [wasClean:%s, code:%s, reason:"%s"]',
logger.warn(
'WebSocket "close" event [wasClean:%s, code:%s, reason:"%s"]',
event.wasClean, event.code, event.reason);

@@ -148,3 +156,3 @@

{
this.emit('failed', currentAttempt);
this.safeEmit('failed', currentAttempt);

@@ -162,3 +170,3 @@ if (this._closed)

this.emit('disconnected');
this.safeEmit('disconnected');

@@ -168,3 +176,3 @@ if (this._closed)

this._setWebSocket();
this._runWebSocket();

@@ -178,3 +186,3 @@ return;

// Emit 'close' event.
this.emit('close');
this.safeEmit('close');
};

@@ -202,3 +210,4 @@

{
logger.error('no listeners for WebSocket "message" event, ignoring received message');
logger.error(
'no listeners for WebSocket "message" event, ignoring received message');

@@ -209,3 +218,3 @@ return;

// Emit 'message' event.
this.emit('message', message);
this.safeEmit('message', message);
};

@@ -212,0 +221,0 @@ });

@@ -1,13 +0,9 @@

const randomNumber = require('random-number');
const randomNumberGenerator = randomNumber.generator(
{
min : 1000000,
max : 9999999,
integer : true
});
module.exports =
/**
* Generates a random positive integer.
*
* @returns {Number}
*/
exports.generateRandomNumber = function()
{
randomNumber : randomNumberGenerator
return Math.round(Math.random() * 10000000);
};
{
"name": "protoo-client",
"version": "3.0.3",
"description": "protoo JavaScript client library",
"version": "4.0.0",
"description": "protoo JavaScript client module",
"author": "Iñaki Baz Castillo <ibc@aliax.net>",

@@ -10,7 +10,12 @@ "homepage": "https://protoojs.org",

"type": "git",
"url": "git+https://github.com/ibc/protoo.git"
"url": "https://github.com/ibc/protoo.git"
},
"main": "lib/index.js",
"keywords": [
"nodejs",
"browser",
"websocket"
],
"engines": {
"node": ">=6.4"
"node": ">=8.0.0"
},

@@ -21,9 +26,8 @@ "scripts": {

"dependencies": {
"debug": "^4.1.0",
"debug": "^4.1.1",
"events": "^3.0.0",
"random-number": "0.0.9",
"retry": "^0.12.0"
},
"devDependencies": {
"eslint": "^5.10.0"
"eslint": "^5.13.0"
},

@@ -30,0 +34,0 @@ "optionalDependencies": {