Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
Stop calling the external command in port-plugin.
Browse files Browse the repository at this point in the history
Signed-off-by: Masaki Muranaka <monaka@monami-ya.com>
  • Loading branch information
monaka authored and evidolob committed Jul 15, 2019
1 parent 2a903f1 commit 149dbaf
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 169 deletions.
1 change: 1 addition & 0 deletions plugins/ports-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@eclipse-che/plugin": "latest",
"@theia/plugin": "0.8.0",
"@theia/plugin-packager": "latest",
"@types/jest": "24.0.3",
"@types/node": "11.9.4"
},
"scripts": {
Expand Down
42 changes: 0 additions & 42 deletions plugins/ports-plugin/src/__mocks__/command.ts

This file was deleted.

19 changes: 0 additions & 19 deletions plugins/ports-plugin/src/cli-error.ts

This file was deleted.

42 changes: 0 additions & 42 deletions plugins/ports-plugin/src/command.ts

This file was deleted.

8 changes: 6 additions & 2 deletions plugins/ports-plugin/src/port-changes-detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { PortScanner } from './port-scanner';
import { PortScanner, AbstractInternalScanner } from './port-scanner';
import { Port } from './port';

interface PortCallback {
Expand All @@ -24,7 +24,7 @@ export class PortChangesDetector {
private static readonly WAIT = 3000;
private openedPorts: Port[] = [];

private portScanner: PortScanner = new PortScanner();
private readonly portScanner: PortScanner;

private onDidOpenPorts: ((openPort: Port) => void)[] = [];
private onDidClosePorts: ((closedPort: Port) => void)[] = [];
Expand All @@ -37,6 +37,10 @@ export class PortChangesDetector {
this.onDidClosePorts.push(callback);
}

constructor(internalScanner?: AbstractInternalScanner) {
this.portScanner = new PortScanner(internalScanner);
}

/**
* Get opened ports.
*/
Expand Down
72 changes: 59 additions & 13 deletions plugins/ports-plugin/src/port-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,80 @@
**********************************************************************/

import { Port } from './port';
import { Command } from './command';
import { IpConverter } from './ip-converter';
import { readFile } from 'fs';

/**
* Injectrable internal scanner used with PortScanner.
* @author Masaki Muranaka <monaka@monami-ya.com>
*/
export abstract class AbstractInternalScanner {
public readFilePromise(path: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
readFile(path, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data.toString());
}
});
});
}
abstract getListeningPortV4(): Promise<string>;
abstract getListeningPortV6(): Promise<string>;

}

/**
* Default internal scanner used with PortScanner.
* @author Masaki Muranaka <monaka@monami-ya.com>
*/
class DefaultInternalScanner extends AbstractInternalScanner {
public static readonly PORTS_IPV4 = '/proc/net/tcp';
public static readonly PORTS_IPV6 = '/proc/net/tcp6';
private fetchIPV4 = true;
private fetchIPV6 = true;

async getListeningPortV4() {
return this.fetchIPV4 ? this.readFilePromise(DefaultInternalScanner.PORTS_IPV4)
.catch(e => {
console.error(e);
this.fetchIPV4 = false;
return Promise.resolve('');
}) : '';
}

async getListeningPortV6() {
return this.fetchIPV6 ? this.readFilePromise(DefaultInternalScanner.PORTS_IPV6)
.catch(e => {
console.error(e);
this.fetchIPV6 = false;
return Promise.resolve('');
}) : '';
}
}

/**
* Allow to grab ports being opened and on which network interface
* @author Florent Benoit
*/
export class PortScanner {
private scanner: AbstractInternalScanner;

public static readonly GRAB_PORTS_IPV4 = 'cat /proc/net/tcp';
public static readonly GRAB_PORTS_IPV6 = 'cat /proc/net/tcp6';
/* `scanner` will be injected on tests. */
constructor(scanner: AbstractInternalScanner = new DefaultInternalScanner()) {
this.scanner = scanner;
}

/**
* Get opened ports.
*/
public async getListeningPorts(): Promise<Port[]> {

const ipConverter = new IpConverter();
// connect to /proc/net/tcp and /proc/net/tcp6
const command = new Command(__dirname);
const outputv4 = await command.exec(PortScanner.GRAB_PORTS_IPV4);
const outputv6 = await command.exec(PortScanner.GRAB_PORTS_IPV6);

// assembe ipv4 and ipv6 output
const output = `
${outputv4}
${outputv6}
`;
const outIPV6 = this.scanner.getListeningPortV6();
const outIPV4 = this.scanner.getListeningPortV4();
const output = (await Promise.all([outIPV4, outIPV6])).join();

// parse
const regex = /:\s(.*):(.*)\s[0-9].*\s0A\s/gm;
Expand Down
32 changes: 0 additions & 32 deletions plugins/ports-plugin/tests/command.spec.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,35 @@
**********************************************************************/

import * as fs from "fs";
import { PortScanner } from "../../src/port-scanner";
import { PortScanner, AbstractInternalScanner } from "../../src/port-scanner";
import { PortChangesDetector } from "../../src/port-changes-detector";
import { Command } from "../../src/command";
import { Port } from "../../src/port";

jest.mock("../../src/command");
class DummyInternalScanner extends AbstractInternalScanner {
private path_: string;

describe("Test Port Changes", () => {
set path(path_: string) {
this.path_ = path_;
}

async getListeningPortV4() {
return super.readFilePromise(this.path_);
}
async getListeningPortV6() {
return super.readFilePromise("/dev/null");
}
}

describe("Test Port Changes", () => {
let dummyInternalScanner = new DummyInternalScanner();
let portChangesDetector: PortChangesDetector;

beforeEach(() => {
portChangesDetector = new PortChangesDetector();
portChangesDetector = new PortChangesDetector(dummyInternalScanner);
});

test("test events triggered", async () => {
const outputBefore = fs.readFileSync(__dirname + "/port-changes-detector-before.stdout");
(Command as any).__setExecCommandOutput(PortScanner.GRAB_PORTS_IPV4, outputBefore);
dummyInternalScanner.path = __dirname + "/port-changes-detector-before.stdout";

// register callbacks
const newOpenedPorts: Port[] = [];
Expand All @@ -39,8 +50,7 @@ describe("Test Port Changes", () => {
await portChangesDetector.init();

// change output
const outputAfter = fs.readFileSync(__dirname + "/port-changes-detector-after.stdout");
(Command as any).__setExecCommandOutput(PortScanner.GRAB_PORTS_IPV4, outputAfter);
dummyInternalScanner.path = __dirname + "/port-changes-detector-after.stdout";

// monitor
await portChangesDetector.check();
Expand Down
34 changes: 24 additions & 10 deletions plugins/ports-plugin/tests/port-scanner/port-scanner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,26 @@
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import * as fs from "fs";
import { PortScanner } from "../../src/port-scanner";
import { Command } from "../../src/command";
import { PortScanner, AbstractInternalScanner } from "../../src/port-scanner";

jest.mock("../../src/command");
class DummyInternalScanner extends AbstractInternalScanner {
async getListeningPortV4() {
return super.readFilePromise(__dirname + "/port-scanner-listen-ipv4.stdout");
}
async getListeningPortV6() {
return super.readFilePromise(__dirname + "/port-scanner-listen-ipv6.stdout");
}
}

describe("Test Port Scanner", () => {
describe("Test Port Scanner with dummy data", () => {

let portScanner: PortScanner;

beforeEach(() => {
portScanner = new PortScanner();
portScanner = new PortScanner(new DummyInternalScanner());
});

test("test port opened", async () => {
const outputIpv4 = fs.readFileSync(__dirname + "/port-scanner-listen-ipv4.stdout");
const outputIpv6 = fs.readFileSync(__dirname + "/port-scanner-listen-ipv6.stdout");
(Command as any).__setExecCommandOutput(PortScanner.GRAB_PORTS_IPV4, outputIpv4);
(Command as any).__setExecCommandOutput(PortScanner.GRAB_PORTS_IPV6, outputIpv6);
const ports = await portScanner.getListeningPorts();
expect(ports).toBeDefined();
expect(Array.isArray(ports)).toBe(true);
Expand All @@ -44,3 +45,16 @@ describe("Test Port Scanner", () => {
});

});

describe("Test Port Scanner with real path", () => {
let portScanner: PortScanner;

beforeEach(() => {
portScanner = new PortScanner();
});

test("test no unhandled exception is thrown", async () => {
await portScanner.getListeningPorts();
await portScanner.getListeningPorts();
});
});
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@
"dev-packages/*/src",
"plugins/*/src",
"extensions/*/src"
],
"types": [
"node", "jest"
]
}

0 comments on commit 149dbaf

Please sign in to comment.