gpii-windows
Version:
Components of the GPII personalization infrastructure for use on Microsoft's "Windows" ™
185 lines (161 loc) • 5.53 kB
JavaScript
/* A child process used by some tests.
*
* Command line options:
*
* inherited-pipe File descriptor 3 will be read from and written to. This tests the pipe inheritance.
*
* named-pipe PIPE Open the named pipe "PIPE" and send some information about the process is sent on it. This tests
* starting a client.
*
* mutex MUTEX Creates a mutex, and releases it after 10 seconds. Used to detect if this process has been run.
*
* Copyright 2017 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The R&D leading to these results received funding from the
* Department of Education - Grant H421A150005 (GPII-APCP). However,
* these results do not necessarily represent the policy of the
* Department of Education, and you should not assume endorsement by the
* Federal Government.
*
* You may obtain a copy of the License at
* https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
;
var logFile = null;
var fs = require("fs");
function log() {
var items = Array.from(arguments);
if (logFile) {
fs.appendFileSync(logFile, items.join(" ") + "\n");
} else {
console.log.apply(console, items);
}
}
function fail() {
var args = Array.from(arguments);
args.unshift("FAIL:");
log.apply(log, args);
process.exit(1);
}
process.on("uncaughtException", function (e) {
fail(e);
process.exit(1);
});
log("child started");
function setEvent(eventHandle) {
var ffi = require("ffi-napi");
var kernel32 = ffi.Library("kernel32", {
"SetEvent": [
"int", [ "uint" ]
]
});
log("Calling SetEvent:", eventHandle);
var ret = kernel32.SetEvent(eventHandle);
log("SetEvent returned ", ret);
return ret;
}
var actions = {
/**
* For the gpii-ipc.startProcess test: Read to and from a pipe.
*/
"inherited-pipe": function () {
// Standard output isn't available to this process, so write output to a file.
logFile = process.argv[3];
log("child started");
var net = require("net");
// Get the pipe name.
var pipeId = process.env.GPII_SERVICE_PIPE;
if (!pipeId) {
fail("GPII_SERVICE_PIPE not set.");
process.exit(1);
} else {
log("GPII_SERVICE_PIPE:", pipeId);
}
// expecting pipe:id
var prefix = "pipe:";
if (!pipeId.startsWith(prefix)) {
fail("GPII_SERVICE_PIPE is badly formed");
}
var pipeName = "\\\\.\\pipe\\gpii-" + pipeId.substr(prefix.length);
var pipe = net.connect(pipeName, function () {
log("client: connected to server");
var authenticated = false;
var allData = "";
pipe.on("data", function (data) {
allData += data;
if (allData.indexOf("\n") >= 0) {
log("Got data:", allData);
if (authenticated) {
// Echo what was received.
pipe.write("received: " + allData);
} else {
var match = allData.match(/^challenge:([0-9]+)\n$/);
if (!match || !match[1]) {
fail("Invalid authentication challenge: '" + allData + "'");
}
var eventHandle = parseInt(match[1]);
setEvent(eventHandle);
authenticated = true;
}
allData = "";
}
});
});
pipe.on("error", function (err) {
if (err.code === "EOF") {
process.nextTick(process.exit);
} else {
log("input error", err);
throw err;
}
});
},
"validate-client": function () {
var eventHandle = parseInt(process.argv[3]);
setEvent(eventHandle);
},
/**
* For the gpii-ipc.execute test: send some information to the pipe named on the command line.
*/
"named-pipe": function () {
var net = require("net");
var info = {
env: process.env,
currentDir: process.cwd()
};
var pipeName = process.argv[3];
var connection = net.createConnection(pipeName, function () {
log("connected");
connection.write(JSON.stringify(info));
connection.end();
});
},
/**
* For the process-monitor.startProcess test: Create a mutex. The parent will check if this mutex exists in order
* to determine this process has been started.
*/
"mutex": function () {
var winapi = require("../src/winapi.js");
var mutexName = winapi.stringToWideChar(process.argv[3]);
var mutex = null;
// Release the mutex and die after 30 seconds.
setTimeout(function () {
if (mutex) {
winapi.kernel32.ReleaseMutex(mutex);
winapi.kernel32.CloseHandle(mutex);
}
}, 30000);
mutex = winapi.kernel32.CreateMutexW(winapi.NULL, true, mutexName);
log("mutex", winapi.stringFromWideChar(mutexName), mutex);
}
};
var option = process.argv[2];
if (actions[option]) {
actions[option]();
} else {
log("Unrecognised command line");
process.exit(1);
}