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

arc-rpc

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

arc-rpc - npm Package Compare versions

Comparing version 1.3.2 to 1.3.3

487

index.js
'use strict'; // always strict mode
// Import dependencies
const EventEmitter = require ('events').EventEmitter;
const uuid = require ('uuid');
const ipc = require ('node-ipc');
const nacl = require ('tweetnacl');
const EventEmitter = require ('events').EventEmitter;
const uuid = require ('uuid');
const SocketIo = require ('socket.io');
const SocketIoClient = require ('socket.io-client');
const nacl = require ('tweetnacl');
// Create RPC events class
class RpcEvents extends EventEmitter {
constructor (stream) {
super ();
constructor (stream) {
super ();
this._stream = stream;
this._listen ();
}
// Store stream variable as property and listen for events
this._stream = stream;
this._listen ();
}
send (id, ...params) {
// Emit event to remote
this._stream.send ('evt', {
params : params,
id : id,
});
}
send (id, ...params) {
// Emit event to remote
this._stream.send ('evt', {
params : params,
id : id,
});
}
_listen () {
// Listen for remote user events
this._stream.on ('evt', (data) => {
// Rebroadcast to listeners on self
this.emit (data.id, ...data.params);
});
}
_listen () {
// Listen for remote user events
this._stream.on ('evt', (data) => {
// Rebroadcast to listeners on self
this.emit (data.id, ...data.params);
});
}
}

@@ -37,287 +39,278 @@

class Rpc extends EventEmitter {
constructor (stream, child) {
// Induce spawning of parent/super event emitter
super ();
constructor (stream, child) {
// Induce spawning of parent/super event emitter
super ();
// Set own ID for identification
this.id = uuid ();
// Set own ID for identification
this.id = uuid ();
// Set mock for accessing methods
this.class = this._genClass ();
// Set mock for accessing methods
this.class = this._genClass ();
// Set child for handling plain events
this.events = new RpcEvents (stream);
// Set child for handling plain events
this.events = new RpcEvents (stream);
// Set private variables
this._stream = stream;
this._child = child;
// Give child class instance a copy of this/RPC
if (child._handleRpc != null) child._handleRpc (this);
// Listen for events if have child class
if (child != null) this._listen ();
}
// Set private variables
this._stream = stream;
this._child = child;
_genClass () {
// Create handler for proxy class
let proxyHandler = {
// Handle get on proxy class
get: (target, property) => {
// Return function which takes all trailing params
return (async (...params) => {
// Issue remote call with property name and recieved params
let result = await this._call (property, params);
// Listen for events if have child class
if (child != null) this._listen ();
}
// Check if response is error
if (result.isError) {
// Throw if error to emulate native function
throw result.data;
} else {
// Non error, simply return data
return result.data;
}
});
},
};
_genClass () {
// Create handler for proxy class
let proxyHandler = {
// Handle get on proxy class
get: (target, property) => {
// Return function which takes all trailing params
return (async (...params) => {
// Issue remote call with property name and recieved params
let result = await this._call (property, params);
// Create a new `Proxy` to act as our class
let proxy = new Proxy ({}, proxyHandler);
// Check if response is error
if (result.isError) {
// Throw if error to emulate native function
throw result.data;
} else {
// Non error, simply return data
return result.data;
}
});
},
};
// Return the proxy
return proxy;
}
// Create a new `Proxy` to act as our class
let proxy = new Proxy ({}, proxyHandler);
_listen () {
// Listen for function calls
this._stream.on ('fnCall', async (call) => {
// Create response variable on higher scope
let response = null;
// Return the proxy
return proxy;
}
// Find internal handler
let handler = this._child[call.fnId];
_listen () {
// Listen for function calls
this._stream.on ('fnCall', async (call) => {
// Create response variable on higher scope
let response = null;
// Handle inexistence
if (handler == null) {
this._stream.send ('fnRes.' + call.resId, {
isError: true,
data: "No such method",
});
// Find internal handler
let handler = this._child[call.fnId].bind(this._child);
return;
}
// Handle inexistence
if (handler == null) {
this._stream.send ('fnRes.' + call.resId, {
isError : true,
data : 'No such method',
});
// Try getting response from handler or handle error
try {
// Run with applied params and await result
response = await handler (...call.params);
} catch (err) {
// Emit error as response
this._stream.send ('fnRes.' + call.resId, {
isError: true,
data: err,
});
return;
}
return;
}
// Try getting response from handler or handle error
try {
// Run with applied params and await result
response = await handler (...call.params);
} catch (err) {
// Emit error as response
this._stream.send ('fnRes.' + call.resId, {
isError: true,
data: err,
});
// Emit success and function return result
this._stream.send ('fnRes.' + call.resId, {
isError: false,
data: response,
});
});
}
return;
}
async _call (fnId, params) {
// Generate ID to listen for responses on
let resId = uuid ();
// Emit success and function return result
this._stream.send ('fnRes.' + call.resId, {
isError: false,
data: response,
});
});
}
// Emit the remote call event
this._stream.send ('fnCall', {
fnId: fnId,
resId: resId,
params: params,
});
async _call (fnId, params) {
// Generate ID to listen for responses on
let resId = uuid ();
// Create and await a promise to get function response
let response = await new Promise ((resolve, reject) => {
// Listen for a response on generated response ID
this._stream.once ('fnRes.' + resId, (response) => {
// Resolve promise with recieved data
resolve (response);
});
});
// Emit the remote call event
this._stream.send ('fnCall', {
fnId: fnId,
resId: resId,
params: params,
});
return response;
}
// Create and await a promise to get function response
let response = await new Promise ((resolve, reject) => {
// Listen for a response on generated response ID
this._stream.once ('fnRes.' + resId, (response) => {
// Resolve promise with recieved data
resolve (response);
});
});
// Induced by implementations of `Rpc`
_disconnect () {
this.emit ('disconnect');
}
return response;
}
// Induced by implementations of `Rpc`
_disconnect () {
// Emit disconnect event so users of RPC will be aware
this.emit ('disconnect');
}
}
class ServerIpcInterface extends EventEmitter {
constructor (socket, cryptKey, onDisconnect) {
super ();
class ServerSocketInterface extends EventEmitter {
constructor (socket, cryptKey, onDisconnect) {
super ();
// Set private class variables
this._socket = socket;
this._onDisconnect = onDisconnect;
this._cryptKey = cryptKey;
// Set private class variables
this._socket = socket;
this._onDisconnect = onDisconnect;
this._cryptKey = cryptKey;
this._listen ();
}
// Listen for IPC data
this._listen ();
}
_listen () {
ipc.server.on ('message', (data, socket) => {
if (socket.id != this._socket.id) {
return // Not for our socket, ignore
}
_listen () {
this._socket.on ('message', (data) => {
// silently ignore bad data
if (data.nonce == null || data.encrypted == null) return;
// silently ignore bad data
if (data.nonce == null || data.encrypted == null) return;
// open nacl secret box
let decrypted = nacl.secretbox.open (Buffer.from (data.encrypted, 'base64'), Buffer.from (data.nonce, 'base64'), this._cryptKey);
// open nacl secret box
let decrypted = nacl.secretbox.open (Buffer.from (data.encrypted, 'base64'), Buffer.from (data.nonce, 'base64'), this._cryptKey);
// silently ignore bad crypt, TODO: handle
if (decrypted == false) return;
// silently ignore bad crypt, TODO: handle
if (decrypted == false) return;
// decode JSON message
let decoded = JSON.parse (Buffer.from (decrypted).toString ());
// decode JSON message
let decoded = JSON.parse (Buffer.from (decrypted).toString ());
// emit event
this.emit (decoded.id, decoded.data);
});
// emit event
this.emit (decoded.id, decoded.data);
});
this._socket.on ('disconnect', () => {
// Run self ondisconnect to handle server disconnection
this._onDisconnect ();
});
}
ipc.server.on ('socket.disconnected', (socket) => {
if (socket.id != this._socket.id) {
return // Not for our socket, ignore
}
send (id, data) {
// Encode object to JSON
let encoded = JSON.stringify ({
'id' : id,
'data' : data
});
this._onDisconnect ();
});
}
// Generate a random nonce for cryptography
let nonce = nacl.randomBytes (nacl.box.nonceLength);
send (id, data) {
// Encode object to JSON
let encoded = JSON.stringify ({
'id' : id,
'data' : data
});
// Encrypt encoded object using nonce, hardcoded server public key and our secret key
let encrypted = nacl.secretbox (Buffer.from (encoded), nonce, this._cryptKey);
// Generate a random nonce for cryptography
let nonce = nacl.randomBytes (nacl.box.nonceLength);
// Send nonce, from secret key, and encrypted data over IPC
this._socket.emit ('message', {
'nonce' : Buffer.from (nonce).toString ('base64'),
'encrypted' : Buffer.from (encrypted).toString ('base64')
});
}
}
// Encrypt encoded object using nonce, hardcoded server public key and our secret key
let encrypted = nacl.secretbox (Buffer.from (encoded), nonce, this._cryptKey);
class ServerSocketRpc extends Rpc {
constructor (socket, cryptKey, child) {
// Create event interface from provided ipc socket
let ipcInterface = new ServerSocketInterface (socket, cryptKey, () => {
// Induce self disconnect when socket interface disconnected
this._disconnect ();
});
// Send nonce, from secret key, and encrypted data over IPC
ipc.server.emit (this._socket, 'message', {
'nonce' : Buffer.from (nonce).toString ('base64'),
'encrypted' : Buffer.from (encrypted).toString ('base64')
});
}
// Create parent RPC instance using interface as stream
super (ipcInterface, child);
}
}
class ServerIpcRpc extends Rpc {
constructor (socket, cryptKey, child) {
// Create event interface from provided ipc socket
let ipcInterface = new ServerIpcInterface (socket, cryptKey, () => {
// Induce self disconnect when socket interface disconnected
this._disconnect ();
});
class ServerSocketRpcMaster extends EventEmitter {
constructor(port, cryptKey, child) {
super ();
// Create parent RPC instance using interface as stream
super (ipcInterface, child);
}
}
let socketIo = new SocketIo ();
class ServerIpcRpcMaster extends EventEmitter {
constructor(namespace, cryptKey, child) {
super ();
socketIo.on ('connection', (socket) => {
let clientRpc = new ServerSocketRpc (socket, cryptKey, child);
this.emit ('client', clientRpc);
});
// Build IPC
ipc.config.id = namespace;
ipc.config.retry = 1500;
ipc.config.silent = true;
// Start IPC server
ipc.serve ();
ipc.server.start ();
ipc.server.on ('connect', (socket) => {
let clientRpc = new ServerIpcRpc (socket, cryptKey, child);
this.emit ('client', clientRpc);
});
}
socketIo.listen (port);
}
}
class ClientIpcInterface extends EventEmitter {
constructor (namespace, cryptKey) {
// Create parent event emitter
super ();
class ClientSocketInterface extends EventEmitter {
constructor (host, port, cryptKey) {
// Create parent event emitter
super ();
this._namespace = namespace;
this._cryptKey = cryptKey;
let socket = SocketIoClient ('http://' + host + ':' + port);
// build ipc
ipc.config.id = namespace;
ipc.config.retry = 1500;
ipc.config.silent = true;
this._cryptKey = cryptKey;
this._socket = socket;
ipc.connectTo (namespace, () => {
this._listen ();
});
}
this._listen ();
}
_listen () {
ipc.of[this._namespace].on ('message', (data) => {
// silently ignore bad data
if (data.nonce == null || data.encrypted == null) return;
// open nacl secret box
let decrypted = nacl.secretbox.open (Buffer.from (data.encrypted, 'base64'), Buffer.from (data.nonce, 'base64'), this._cryptKey);
_listen () {
this._socket.on ('message', (data) => {
// silently ignore bad data
if (data.nonce == null || data.encrypted == null) return;
// silently ignore bad crypt, TODO: handle
if (decrypted == null) return;
// open nacl secret box
let decrypted = nacl.secretbox.open (Buffer.from (data.encrypted, 'base64'), Buffer.from (data.nonce, 'base64'), this._cryptKey);
// decode JSON message
let decoded = JSON.parse (Buffer.from (decrypted).toString ());
// silently ignore bad crypt, TODO: handle
if (decrypted == null) return;
// emit event
this.emit (decoded.id, decoded.data);
});
}
// decode JSON message
let decoded = JSON.parse (Buffer.from (decrypted).toString ());
send (id, data) {
// Encode object to JSON
let encoded = JSON.stringify ({
'id' : id,
'data' : data,
});
// emit event
this.emit (decoded.id, decoded.data);
});
}
// Generate a random nonce for cryptography
let nonce = nacl.randomBytes (nacl.box.nonceLength)
send (id, data) {
// Encode object to JSON
let encoded = JSON.stringify ({
'id' : id,
'data' : data,
});
// Encrypt encoded object using nonce, hardcoded server public key and our secret key
let encrypted = nacl.secretbox (Buffer.from (encoded), nonce, this._cryptKey)
// Generate a random nonce for cryptography
let nonce = nacl.randomBytes (nacl.box.nonceLength)
// Send nonce, from secret key, and encrypted data over IPC
ipc.of[this._namespace].emit ('message', {
'nonce' : Buffer.from (nonce).toString ('base64'),
'encrypted' : Buffer.from (encrypted).toString ('base64')
});
}
// Encrypt encoded object using nonce, hardcoded server public key and our secret key
let encrypted = nacl.secretbox (Buffer.from (encoded), nonce, this._cryptKey)
// Send nonce, from secret key, and encrypted data over IPC
this._socket.emit ('message', {
'nonce' : Buffer.from (nonce).toString ('base64'),
'encrypted' : Buffer.from (encrypted).toString ('base64')
});
}
}
class ClientIpcRpc extends Rpc {
constructor (namespace, cryptKey, client) {
// Create client IPC interface for provided namespace
let ipcInterface = new ClientIpcInterface (namespace, cryptKey);
class ClientSocketRpc extends Rpc {
constructor (host, port, cryptKey, client) {
// Create client IPC interface for provided namespace
let socketInterface = new ClientSocketInterface (host, port, cryptKey);
// Create parent RPC module using interface as stream
super (ipcInterface, client);
}
// Create parent RPC module using interface as stream
super (socketInterface, client);
}
}
exports = module.exports = { ClientIpcRpc, ServerIpcRpcMaster };
// Export classes
exports = module.exports = { Rpc, ClientSocketRpc, ServerSocketRpcMaster };
{
"name": "arc-rpc",
"version": "1.3.2",
"version": "1.3.3",
"description": "Asynchronous Remote Classes make RPC simple",
"main": "index.js",
"dependencies": {
"node-ipc": "^9.0.1",
"socket.io": "^2.0.3",
"socket.io-client": "^2.0.3",
"tweetnacl": "^1.0.0",

@@ -9,0 +10,0 @@ "uuid": "^3.0.1"

@@ -16,3 +16,3 @@ # Arc RPC

Here is a basic example of using RPC with `node-ipc`
Here is a basic example of using RPC with `socket.io`

@@ -22,6 +22,6 @@ `Server.js`

```js
// Include library for IPC-RPC clients
let ClientIpcRpc = require("arc-rpc").ClientIpcRpc
// Include library for socket RPC clients
let ClientSocketRpc = require("arc-rpc").ClientSocketRpc
// Define `serverIpc` in higher scope for testing purposes
// Define `serverRpc` in higher scope for testing purposes
let serverRpc = null

@@ -32,3 +32,3 @@

// Example method
clientTest() {
async clientTest() {
console.log("Remotely called by server, calling server method.")

@@ -44,4 +44,4 @@

// Create RPC to server, on IPC channel testing, predefined encryption key, with an instance of the example client class
serverRpc = new ClientIpcRpc ("testing", Buffer.from ('flbd+mTz8bIWl2DQxFMKHYAA1+PFxpEKmVNsZpFP5xQ=', 'base64'), new ClientClass())
// Create RPC to server over socket.io socket, predefined encryption key, with an instance of the example client class
serverRpc = new ClientSocketRpc ("127.0.0.1", 9919, Buffer.from ('flbd+mTz8bIWl2DQxFMKHYAA1+PFxpEKmVNsZpFP5xQ=', 'base64'), new ClientClass())
```

@@ -52,4 +52,4 @@

```js
// Include library for IPC-RPC servers
let ServerIpcRpcMaster = require("arc-rpc").ServerIpcRpcMaster
// Include library for socket RPC servers
let ServerSocketRpcMaster = require("arc-rpc").ServerSocketRpcMaster

@@ -59,3 +59,3 @@

class ServerClass {
serverTest() {
async serverTest() {
console.log("Remotely called by client.")

@@ -65,7 +65,7 @@ }

// Create RPC master/listener, on IPC channel testing, predefined encryption key, with an instance of the example server class
let rpcMaster = new ServerIpcRpcMaster ("testing", Buffer.from ('flbd+mTz8bIWl2DQxFMKHYAA1+PFxpEKmVNsZpFP5xQ=', 'base64'), new ServerClass())
// Create RPC master/listener, on socket.io connection, predefined encryption key, with an instance of the example server class
let rpcMaster = new ServerSocketRpcMaster (9919, Buffer.from ('flbd+mTz8bIWl2DQxFMKHYAA1+PFxpEKmVNsZpFP5xQ=', 'base64'), new ServerClass())
// Listen for new clients
rpcMaster.on("client", (clientRpc) => {
rpcMaster.on("client", async (clientRpc) => {
console.log("Got new client, remotely calling client test.")

@@ -81,8 +81,4 @@

## Why are you encrypting IPC streams??
This is made for a specific project, soon the node-ipc connections will be replaced with net sockets, or be replaced with a net library. I know, it's silly this way.
## Basic documentation
I'll get to completing this later

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc