Move ping code to own file
This commit is contained in:
1 parent
0e02b7c7ea
commit
77563fc85e
4 files changed
+104
-49
No files matched your search
+3
-8
@@ -21,14 +21,13 @@ import * as url from "url";
|
||||
import * as mongodb from "mongodb";
|
||||
import * as querystring from "querystring";
|
||||
import * as vm from "vm";
|
||||
import { exec } from "child_process";
|
||||
import * as config from "./config";
|
||||
import * as db from "./db";
|
||||
import * as query from "./query";
|
||||
import * as apiFunctions from "./api-functions";
|
||||
import * as cache from "./cache";
|
||||
import { version as VERSION } from "../package.json";
|
||||
import * as os from "os";
|
||||
import { ping } from "./ping";
|
||||
|
||||
const DEVICE_TASKS_REGEX = /^\/devices\/([a-zA-Z0-9\-_%]+)\/tasks\/?$/;
|
||||
const TASKS_REGEX = /^\/tasks\/([a-zA-Z0-9\-_%]+)(\/[a-zA-Z_]*)?$/;
|
||||
@@ -43,10 +42,6 @@ const PROVISIONS_REGEX = /^\/provisions\/([a-zA-Z0-9\-_%]+)\/?$/;
|
||||
const VIRTUAL_PARAMETERS_REGEX = /^\/virtual_parameters\/([a-zA-Z0-9\-_%]+)\/?$/;
|
||||
const FAULTS_REGEX = /^\/faults\/([a-zA-Z0-9\-_%:]+)\/?$/;
|
||||
|
||||
function pingVariant(): string {
|
||||
return os.platform() === "freebsd" ? "-t 1 -c 3" : "-w 1 -i 0.2 -c 3";
|
||||
}
|
||||
|
||||
function throwError(err, httpResponse?): never {
|
||||
if (httpResponse) {
|
||||
httpResponse.writeHead(500, { Connection: "close" });
|
||||
@@ -596,9 +591,9 @@ export function listener(request, response): void {
|
||||
}
|
||||
} else if (PING_REGEX.test(urlParts.pathname)) {
|
||||
const host = querystring.unescape(PING_REGEX.exec(urlParts.pathname)[1]);
|
||||
const pingArgs = pingVariant();
|
||||
exec(`ping ${pingArgs} ${host}`, (err, stdout) => {
|
||||
ping(host, (err, res, stdout) => {
|
||||
if (err) {
|
||||
if (!res) throwError(err, response);
|
||||
response.writeHead(404, { "Cache-Control": "no-cache" });
|
||||
response.end(`${err.name}: ${err.message}`);
|
||||
return;
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Copyright 2013-2019 GenieACS Inc.
|
||||
*
|
||||
* This file is part of GenieACS.
|
||||
*
|
||||
* GenieACS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* GenieACS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { platform } from "os";
|
||||
import { exec } from "child_process";
|
||||
|
||||
interface Ping {
|
||||
packetsTransmitted: number;
|
||||
packetsReceived: number;
|
||||
packetLoss: number;
|
||||
min: number;
|
||||
avg: number;
|
||||
max: number;
|
||||
mdev: number;
|
||||
}
|
||||
|
||||
export function ping(
|
||||
host: string,
|
||||
callback: (err, res?, stdout?) => void
|
||||
): void {
|
||||
let cmd: string, parseRegExp1: RegExp, parseRegExp2: RegExp;
|
||||
switch (platform()) {
|
||||
case "linux":
|
||||
cmd = `ping -w 1 -i 0.2 -c 3 ${host}`;
|
||||
parseRegExp1 = /(\d+) packets transmitted, (\d+) received, ([\d.]+)% packet loss[^]*([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/;
|
||||
parseRegExp2 = /(\d+) packets transmitted, (\d+) received, ([\d.]+)% packet loss/;
|
||||
break;
|
||||
|
||||
case "freebsd":
|
||||
// Send a single packet because on FreeBSD only superuser can send
|
||||
// packets that are only 200 ms apart.
|
||||
cmd = `ping -t 1 -c 3 ${host}`;
|
||||
parseRegExp1 = /(\d+) packets transmitted, (\d+) packets received, ([\d.]+)% packet loss\nround-trip min\/avg\/max\/stddev = ([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+) ms/;
|
||||
parseRegExp2 = /(\d+) packets transmitted, (\d+) packets received, ([\d.]+)% packet loss/;
|
||||
break;
|
||||
|
||||
default:
|
||||
return callback(new Error("Platform not supported"));
|
||||
}
|
||||
|
||||
exec(cmd, (err, stdout) => {
|
||||
let parsed: Ping;
|
||||
if (stdout) {
|
||||
const m1 = stdout.match(parseRegExp1);
|
||||
if (m1) {
|
||||
parsed = {
|
||||
packetsTransmitted: +m1[1],
|
||||
packetsReceived: +m1[2],
|
||||
packetLoss: +m1[3],
|
||||
min: +m1[4],
|
||||
avg: +m1[5],
|
||||
max: +m1[6],
|
||||
mdev: +m1[7]
|
||||
};
|
||||
} else {
|
||||
const m2 = stdout.match(parseRegExp2);
|
||||
if (m2) {
|
||||
parsed = {
|
||||
packetsTransmitted: +m2[1],
|
||||
packetsReceived: +m2[2],
|
||||
packetLoss: +m2[3],
|
||||
min: null,
|
||||
avg: null,
|
||||
max: null,
|
||||
mdev: null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback(err, parsed, stdout);
|
||||
});
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { exec } from "child_process";
|
||||
import { ObjectID } from "mongodb";
|
||||
import * as db from "./db";
|
||||
import { del } from "../cache";
|
||||
@@ -29,17 +28,6 @@ import {
|
||||
connectionRequest,
|
||||
deleteDevice
|
||||
} from "../api-functions";
|
||||
import * as os from "os";
|
||||
|
||||
function pingVariant(): string {
|
||||
return os.platform() === "freebsd" ? "-t 1 -c 3" : "-w 1 -i 0.2 -c 3";
|
||||
}
|
||||
|
||||
function pingOutRegex(): RegExp {
|
||||
return os.platform() === "freebsd"
|
||||
? /(\d) packets transmitted, (\d) packets received, ([\d.%]+) packet loss\nround-trip min\/avg\/max\/stddev = ([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+) ms/
|
||||
: /(\d) packets transmitted, (\d) received, ([\d.%]+) packet loss[^]*([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/;
|
||||
}
|
||||
|
||||
async function deleteFault(id): Promise<void> {
|
||||
const deviceId = id.split(":", 1)[0];
|
||||
@@ -160,28 +148,6 @@ interface PingResponse {
|
||||
mdev: number;
|
||||
}
|
||||
|
||||
export function ping(host): Promise<PingResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const pingArgs = pingVariant();
|
||||
exec(`ping ${pingArgs} ${host}`, (err, stdout) => {
|
||||
if (err) return void reject(err);
|
||||
|
||||
const m = stdout.match(pingOutRegex());
|
||||
if (!m) return void reject(new Error("Could not parse ping response"));
|
||||
|
||||
resolve({
|
||||
packetsTransmitted: +m[1],
|
||||
packetsReceived: +m[2],
|
||||
packetLoss: m[3],
|
||||
min: +m[4],
|
||||
avg: +m[5],
|
||||
max: +m[6],
|
||||
mdev: +m[7]
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function putResource(resource, id, data): Promise<void> {
|
||||
if (resource === "presets") {
|
||||
await db.putPreset(id, data);
|
||||
|
||||
+12
-7
@@ -29,6 +29,7 @@ import { QueryOptions, Expression } from "../types";
|
||||
import { generateSalt, hashPassword } from "../auth";
|
||||
import { del } from "../cache";
|
||||
import Authorizer from "../common/authorizer";
|
||||
import { ping } from "../ping";
|
||||
|
||||
const router = new Router();
|
||||
export default router;
|
||||
@@ -551,13 +552,17 @@ router.post("/devices/:id/tags", async (ctx, next) => {
|
||||
});
|
||||
|
||||
router.get("/ping/:host", async ctx => {
|
||||
try {
|
||||
ctx.body = await apiFunctions.ping(ctx.params.host);
|
||||
} catch (err) {
|
||||
ctx.status = 404;
|
||||
ctx.response.headers["Cache-Control"] = "no-cache";
|
||||
ctx.body = `${err.name}: ${err.message}`;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
ping(ctx.params.host, (err, parsed) => {
|
||||
if (parsed) {
|
||||
ctx.body = parsed;
|
||||
} else {
|
||||
ctx.status = 500;
|
||||
ctx.body = `${err.name}: ${err.message}`;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
router.put("/users/:id/password", async (ctx, next) => {
|
||||
|
||||
Reference in new issue
Block a user