Add stdio sources (#17)

This commit is contained in:
Kyle Carberry
2019-01-23 11:52:58 -06:00
parent 704a0defc9
commit 4cd6bed8d2
10 changed files with 157 additions and 47 deletions

View File

@@ -8,6 +8,7 @@ import { SendableConnection } from "../common/connection";
import { ServerOptions } from "./server";
export interface Process {
stdio?: Array<stream.Readable | stream.Writable>;
stdin?: stream.Writable;
stdout?: stream.Readable;
stderr?: stream.Readable;
@@ -69,27 +70,34 @@ export const handleNewSession = (connection: SendableConnection, newSession: New
};
}
const sendOutput = (_fd: SessionOutputMessage.FD, msg: string | Uint8Array): void => {
const sendOutput = (_source: SessionOutputMessage.Source, msg: string | Uint8Array): void => {
const serverMsg = new ServerMessage();
const d = new SessionOutputMessage();
d.setId(newSession.getId());
d.setData(typeof msg === "string" ? new TextEncoder().encode(msg) : msg);
d.setFd(SessionOutputMessage.FD.STDOUT);
d.setSource(_source);
serverMsg.setSessionOutput(d);
connection.send(serverMsg.serializeBinary());
};
if (process.stdout && process.stderr) {
process.stdout.on("data", (data) => {
sendOutput(SessionOutputMessage.FD.STDOUT, data);
sendOutput(SessionOutputMessage.Source.STDOUT, data);
});
process.stderr.on("data", (data) => {
sendOutput(SessionOutputMessage.FD.STDERR, data);
sendOutput(SessionOutputMessage.Source.STDERR, data);
});
} else {
process.on("data", (data) => {
sendOutput(SessionOutputMessage.FD.STDOUT, Buffer.from(data));
sendOutput(SessionOutputMessage.Source.STDOUT, Buffer.from(data));
});
}
if (process.stdio && process.stdio[3]) {
// We have ipc fd
process.stdio[3].on("data", (data) => {
sendOutput(SessionOutputMessage.Source.IPC, data);
});
}

View File

@@ -1,11 +1,11 @@
import * as os from "os";
import * as cp from "child_process";
import * as path from "path";
import { mkdir } from "fs";
import { mkdir, WriteStream } from "fs";
import { promisify } from "util";
import { TextDecoder } from "text-encoding";
import { logger, field } from "@coder/logger";
import { ClientMessage, WorkingInitMessage, ServerMessage, NewSessionMessage } from "../proto";
import { ClientMessage, WorkingInitMessage, ServerMessage, NewSessionMessage, WriteToSessionMessage } from "../proto";
import { evaluate } from "./evaluate";
import { ReadWriteConnection } from "../common/connection";
import { Process, handleNewSession, handleNewConnection } from "./command";
@@ -120,7 +120,16 @@ export class Server {
if (!s) {
return;
}
s.write(new TextDecoder().decode(message.getWriteToSession()!.getData_asU8()));
const data = new TextDecoder().decode(message.getWriteToSession()!.getData_asU8());
const source = message.getWriteToSession()!.getSource();
if (source === WriteToSessionMessage.Source.IPC) {
if (!s.stdio || !s.stdio[3]) {
throw new Error("Cannot send message via IPC to process without IPC");
}
(s.stdio[3] as WriteStream).write(data);
} else {
s.write(data);
}
} else if (message.hasNewConnection()) {
const socket = handleNewConnection(this.connection, message.getNewConnection()!, () => {
this.connections.delete(message.getNewConnection()!.getId());