From 6a8a9256515c08c3d32ea0f84b19c60a93ce77a9 Mon Sep 17 00:00:00 2001 From: "Saurav M. H" Date: Tue, 28 Apr 2020 13:41:51 +0530 Subject: [PATCH 1/4] feat #4: TCP sockets support added --- package-lock.json | 2 +- src/connection/inet-socket-connection.ts | 43 ++++++++++++++++++++++++ src/connection/unix-socket-connection.ts | 2 +- src/juno-node.ts | 25 ++++++++++++-- 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/connection/inet-socket-connection.ts diff --git a/package-lock.json b/package-lock.json index bfafd25..f90d51a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "juno", + "name": "juno-node", "version": "0.0.0", "lockfileVersion": 1, "requires": true, diff --git a/src/connection/inet-socket-connection.ts b/src/connection/inet-socket-connection.ts new file mode 100644 index 0000000..bb35b24 --- /dev/null +++ b/src/connection/inet-socket-connection.ts @@ -0,0 +1,43 @@ +import * as net from 'net'; +import BaseConnection from './base-connection'; + +export default class InetSocketConnection extends BaseConnection { + client?: net.Socket; + host: string; + port: number; + + constructor(host: string, port: number) { + super(); + this.host = host; + this.port = port; + } + + setupConnection(): Promise { + return new Promise(resolve => { + this.client = net.createConnection(this.port, this.host); + this.client.on('data', (data) => { + const dataLines = data.toString().split(/\r?\n/); + dataLines.map((data) => { + if (data) { + this.onData(Buffer.from(data)) + } + }); + }); + this.client.on('connect', () => { + resolve(); + }); + }); + } + + async closeConnection() { + this.client?.destroy(); + } + + send(message: Buffer): Promise { + return new Promise(resolve => { + this.client?.write(message, () => { + resolve(); + }); + }); + } +} diff --git a/src/connection/unix-socket-connection.ts b/src/connection/unix-socket-connection.ts index e6a0735..c75188e 100644 --- a/src/connection/unix-socket-connection.ts +++ b/src/connection/unix-socket-connection.ts @@ -1,7 +1,7 @@ import * as net from 'net'; import BaseConnection from './base-connection'; -export default class SocketConnection extends BaseConnection { +export default class UnixSocketConnection extends BaseConnection { client?: net.Socket; sockPath: string; diff --git a/src/juno-node.ts b/src/juno-node.ts index 14d9825..690fa2b 100644 --- a/src/juno-node.ts +++ b/src/juno-node.ts @@ -1,3 +1,4 @@ +import * as net from 'net'; import { BaseProtocol } from './protocol/base-protocol'; import BaseConnection from './connection/base-connection'; import { JsonProtocol } from './protocol/json-protocol'; @@ -8,7 +9,8 @@ import { TriggerHookRequest, JunoMessage } from './models/messages'; -import SocketConnection from './connection/unix-socket-connection'; +import UnixSocketConnection from './connection/unix-socket-connection'; +import InetSocketConnection from './connection/inet-socket-connection'; export default class JunoModule { @@ -27,8 +29,25 @@ export default class JunoModule { // this.connection.setOnDataListener(this.onDataHandler); } - public static default(socketPath: string): JunoModule { - return new JunoModule(new SocketConnection(socketPath), new JsonProtocol()); + public static async default(socketPath: string) { + if (net.isIP(socketPath.split(':')[0])) { + const [ host, port ] = socketPath.split(':'); + return this.fromInetSocket(host, Number(port)); + } else { + return this.fromUnixSocket(socketPath); + } + } + + public static fromUnixSocket(path: string) { + // Return Error if invoked from windows + if (process.platform == 'win32') { + throw new Error('Unix sockets are not supported on windows'); + } + return new JunoModule(new UnixSocketConnection(path), new JsonProtocol()); + } + + public static fromInetSocket(host: string, port: number) { + return new JunoModule(new InetSocketConnection(host, port), new JsonProtocol()); } public async initialize( From f5d6ca3573c2d4894196434d3afa00603c55ed27 Mon Sep 17 00:00:00 2001 From: "Saurav M. H" Date: Tue, 28 Apr 2020 14:20:05 +0530 Subject: [PATCH 2/4] feat #4: Error handling for socket path --- src/juno-node.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/juno-node.ts b/src/juno-node.ts index 690fa2b..e46ef04 100644 --- a/src/juno-node.ts +++ b/src/juno-node.ts @@ -1,4 +1,5 @@ import * as net from 'net'; +import * as fs from 'fs'; import { BaseProtocol } from './protocol/base-protocol'; import BaseConnection from './connection/base-connection'; import { JsonProtocol } from './protocol/json-protocol'; @@ -30,12 +31,17 @@ export default class JunoModule { } public static async default(socketPath: string) { - if (net.isIP(socketPath.split(':')[0])) { - const [ host, port ] = socketPath.split(':'); + const [ host, port ] = socketPath.split(':'); + + if (net.isIP(host) && typeof Number(port) === 'number') { return this.fromInetSocket(host, Number(port)); - } else { + } + if ( (await fs.promises.lstat(socketPath)).isSocket() ) { return this.fromUnixSocket(socketPath); } + + throw new Error('Invalid socket object'); + } public static fromUnixSocket(path: string) { From 9d6eb535aad22340575468bfb2d192419e20346d Mon Sep 17 00:00:00 2001 From: "Saurav M. H" Date: Tue, 28 Apr 2020 16:25:19 +0530 Subject: [PATCH 3/4] fix #7: Import destructuring and minor fixes --- src/connection/inet-socket-connection.ts | 6 +++--- src/connection/unix-socket-connection.ts | 6 +++--- src/juno-node.ts | 26 ++++++++++++++++-------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/connection/inet-socket-connection.ts b/src/connection/inet-socket-connection.ts index bb35b24..08d1521 100644 --- a/src/connection/inet-socket-connection.ts +++ b/src/connection/inet-socket-connection.ts @@ -1,8 +1,8 @@ -import * as net from 'net'; +import { Socket, createConnection } from 'net'; import BaseConnection from './base-connection'; export default class InetSocketConnection extends BaseConnection { - client?: net.Socket; + client?: Socket; host: string; port: number; @@ -14,7 +14,7 @@ export default class InetSocketConnection extends BaseConnection { setupConnection(): Promise { return new Promise(resolve => { - this.client = net.createConnection(this.port, this.host); + this.client = createConnection(this.port, this.host); this.client.on('data', (data) => { const dataLines = data.toString().split(/\r?\n/); dataLines.map((data) => { diff --git a/src/connection/unix-socket-connection.ts b/src/connection/unix-socket-connection.ts index c75188e..f94800d 100644 --- a/src/connection/unix-socket-connection.ts +++ b/src/connection/unix-socket-connection.ts @@ -1,8 +1,8 @@ -import * as net from 'net'; +import { Socket, createConnection } from 'net'; import BaseConnection from './base-connection'; export default class UnixSocketConnection extends BaseConnection { - client?: net.Socket; + client?: Socket; sockPath: string; constructor(sockPath: string) { @@ -12,7 +12,7 @@ export default class UnixSocketConnection extends BaseConnection { setupConnection(): Promise { return new Promise(resolve => { - this.client = net.createConnection(this.sockPath); + this.client = createConnection(this.sockPath); this.client.on('data', (data) => { const dataLines = data.toString().split(/\r?\n/); dataLines.map((data) => { diff --git a/src/juno-node.ts b/src/juno-node.ts index e46ef04..67011b4 100644 --- a/src/juno-node.ts +++ b/src/juno-node.ts @@ -1,5 +1,5 @@ -import * as net from 'net'; -import * as fs from 'fs'; +import { isIP } from 'net'; +import { promises as fs } from 'fs'; import { BaseProtocol } from './protocol/base-protocol'; import BaseConnection from './connection/base-connection'; import { JsonProtocol } from './protocol/json-protocol'; @@ -33,27 +33,35 @@ export default class JunoModule { public static async default(socketPath: string) { const [ host, port ] = socketPath.split(':'); - if (net.isIP(host) && typeof Number(port) === 'number') { + if (isIP(host) && !isNaN(Number(port))) { return this.fromInetSocket(host, Number(port)); } - if ( (await fs.promises.lstat(socketPath)).isSocket() ) { + if ( (await fs.lstat(socketPath)).isSocket() ) { return this.fromUnixSocket(socketPath); } - throw new Error('Invalid socket object'); + throw new Error('Invalid socket object. Only unix domain sockets and Inet sockets are allowed'); } - public static fromUnixSocket(path: string) { + public static async fromUnixSocket(path: string) { // Return Error if invoked from windows if (process.platform == 'win32') { throw new Error('Unix sockets are not supported on windows'); } - return new JunoModule(new UnixSocketConnection(path), new JsonProtocol()); + if ( (await fs.lstat(path)).isSocket() ) { + return new JunoModule(new UnixSocketConnection(path), new JsonProtocol()); + } + + throw new Error('Invalid unix socket path'); } - public static fromInetSocket(host: string, port: number) { - return new JunoModule(new InetSocketConnection(host, port), new JsonProtocol()); + public static async fromInetSocket(host: string, port: number) { + if (isIP(host) && !isNaN(Number(port))) { + return new JunoModule(new InetSocketConnection(host, port), new JsonProtocol()); + } + + throw new Error('Invalid Inet socket address. Use the format `{host}:{port}`') } public async initialize( From f50d4dbaf60dcc019300db1bf47d36b1ded91f86 Mon Sep 17 00:00:00 2001 From: "Saurav M. H" Date: Tue, 28 Apr 2020 16:32:44 +0530 Subject: [PATCH 4/4] fix #7: fs renamed to fsPromises --- src/juno-node.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/juno-node.ts b/src/juno-node.ts index 67011b4..7bd118d 100644 --- a/src/juno-node.ts +++ b/src/juno-node.ts @@ -1,5 +1,5 @@ import { isIP } from 'net'; -import { promises as fs } from 'fs'; +import { promises as fsPromises } from 'fs'; import { BaseProtocol } from './protocol/base-protocol'; import BaseConnection from './connection/base-connection'; import { JsonProtocol } from './protocol/json-protocol'; @@ -36,7 +36,7 @@ export default class JunoModule { if (isIP(host) && !isNaN(Number(port))) { return this.fromInetSocket(host, Number(port)); } - if ( (await fs.lstat(socketPath)).isSocket() ) { + if ( (await fsPromises.lstat(socketPath)).isSocket() ) { return this.fromUnixSocket(socketPath); } @@ -49,7 +49,7 @@ export default class JunoModule { if (process.platform == 'win32') { throw new Error('Unix sockets are not supported on windows'); } - if ( (await fs.lstat(path)).isSocket() ) { + if ( (await fsPromises.lstat(path)).isSocket() ) { return new JunoModule(new UnixSocketConnection(path), new JsonProtocol()); }