mirror of
https://github.com/coder/code-server.git
synced 2024-12-25 18:52:34 +03:00
Add shared process active message (#16)
* Add shared process active message * Add client function for calling bootstrap fork
This commit is contained in:
parent
72bf4547d4
commit
d827015b40
@ -155,6 +155,15 @@ export class Client {
|
|||||||
return this.doSpawn(modulePath, args, options, true);
|
return this.doSpawn(modulePath, args, options, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VS Code specific.
|
||||||
|
* Forks a module from bootstrap-fork
|
||||||
|
* @param modulePath Path of the module
|
||||||
|
*/
|
||||||
|
public bootstrapFork(modulePath: string): ChildProcess {
|
||||||
|
return this.doSpawn(modulePath, [], undefined, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
public createConnection(path: string, callback?: () => void): Socket;
|
public createConnection(path: string, callback?: () => void): Socket;
|
||||||
public createConnection(port: number, callback?: () => void): Socket;
|
public createConnection(port: number, callback?: () => void): Socket;
|
||||||
public createConnection(target: string | number, callback?: () => void): Socket {
|
public createConnection(target: string | number, callback?: () => void): Socket {
|
||||||
@ -176,13 +185,14 @@ export class Client {
|
|||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
private doSpawn(command: string, args: string[] = [], options?: SpawnOptions, isFork: boolean = false): ChildProcess {
|
private doSpawn(command: string, args: string[] = [], options?: SpawnOptions, isFork: boolean = false, isBootstrapFork: boolean = true): ChildProcess {
|
||||||
const id = this.sessionId++;
|
const id = this.sessionId++;
|
||||||
const newSess = new NewSessionMessage();
|
const newSess = new NewSessionMessage();
|
||||||
newSess.setId(id);
|
newSess.setId(id);
|
||||||
newSess.setCommand(command);
|
newSess.setCommand(command);
|
||||||
newSess.setArgsList(args);
|
newSess.setArgsList(args);
|
||||||
newSess.setIsFork(isFork);
|
newSess.setIsFork(isFork);
|
||||||
|
newSess.setIsBootstrapFork(isBootstrapFork);
|
||||||
if (options) {
|
if (options) {
|
||||||
if (options.cwd) {
|
if (options.cwd) {
|
||||||
newSess.setCwd(options.cwd);
|
newSess.setCwd(options.cwd);
|
||||||
|
@ -5,6 +5,7 @@ import * as stream from "stream";
|
|||||||
import { TextEncoder } from "text-encoding";
|
import { TextEncoder } from "text-encoding";
|
||||||
import { NewSessionMessage, ServerMessage, SessionDoneMessage, SessionOutputMessage, ShutdownSessionMessage, IdentifySessionMessage, ClientMessage, NewConnectionMessage, ConnectionEstablishedMessage, NewConnectionFailureMessage, ConnectionCloseMessage, ConnectionOutputMessage } from "../proto";
|
import { NewSessionMessage, ServerMessage, SessionDoneMessage, SessionOutputMessage, ShutdownSessionMessage, IdentifySessionMessage, ClientMessage, NewConnectionMessage, ConnectionEstablishedMessage, NewConnectionFailureMessage, ConnectionCloseMessage, ConnectionOutputMessage } from "../proto";
|
||||||
import { SendableConnection } from "../common/connection";
|
import { SendableConnection } from "../common/connection";
|
||||||
|
import { ServerOptions } from "./server";
|
||||||
|
|
||||||
export interface Process {
|
export interface Process {
|
||||||
stdin?: stream.Writable;
|
stdin?: stream.Writable;
|
||||||
@ -22,7 +23,7 @@ export interface Process {
|
|||||||
title?: number;
|
title?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleNewSession = (connection: SendableConnection, newSession: NewSessionMessage, onExit: () => void): Process => {
|
export const handleNewSession = (connection: SendableConnection, newSession: NewSessionMessage, serverOptions: ServerOptions | undefined, onExit: () => void): Process => {
|
||||||
let process: Process;
|
let process: Process;
|
||||||
|
|
||||||
const env = {} as any;
|
const env = {} as any;
|
||||||
@ -44,7 +45,15 @@ export const handleNewSession = (connection: SendableConnection, newSession: New
|
|||||||
};
|
};
|
||||||
let proc: cp.ChildProcess;
|
let proc: cp.ChildProcess;
|
||||||
if (newSession.getIsFork()) {
|
if (newSession.getIsFork()) {
|
||||||
proc = cp.fork(newSession.getCommand(), newSession.getArgsList());
|
if (!serverOptions) {
|
||||||
|
throw new Error("No forkProvider set for bootstrap-fork request");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverOptions.forkProvider) {
|
||||||
|
throw new Error("No forkProvider set for server options");
|
||||||
|
}
|
||||||
|
|
||||||
|
proc = serverOptions.forkProvider(newSession);
|
||||||
} else {
|
} else {
|
||||||
proc = cp.spawn(newSession.getCommand(), newSession.getArgsList(), options);
|
proc = cp.spawn(newSession.getCommand(), newSession.getArgsList(), options);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
|
import * as cp from "child_process";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { mkdir } from "fs";
|
import { mkdir } from "fs";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { TextDecoder } from "text-encoding";
|
import { TextDecoder } from "text-encoding";
|
||||||
import { logger, field } from "@coder/logger";
|
import { logger, field } from "@coder/logger";
|
||||||
import { ClientMessage, WorkingInitMessage, ServerMessage } from "../proto";
|
import { ClientMessage, WorkingInitMessage, ServerMessage, NewSessionMessage } from "../proto";
|
||||||
import { evaluate } from "./evaluate";
|
import { evaluate } from "./evaluate";
|
||||||
import { ReadWriteConnection } from "../common/connection";
|
import { ReadWriteConnection } from "../common/connection";
|
||||||
import { Process, handleNewSession, handleNewConnection } from "./command";
|
import { Process, handleNewSession, handleNewConnection } from "./command";
|
||||||
@ -13,6 +14,8 @@ import * as net from "net";
|
|||||||
export interface ServerOptions {
|
export interface ServerOptions {
|
||||||
readonly workingDirectory: string;
|
readonly workingDirectory: string;
|
||||||
readonly dataDirectory: string;
|
readonly dataDirectory: string;
|
||||||
|
|
||||||
|
forkProvider?(message: NewSessionMessage): cp.ChildProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Server {
|
export class Server {
|
||||||
@ -22,7 +25,7 @@ export class Server {
|
|||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly connection: ReadWriteConnection,
|
private readonly connection: ReadWriteConnection,
|
||||||
options?: ServerOptions,
|
private readonly options?: ServerOptions,
|
||||||
) {
|
) {
|
||||||
connection.onMessage((data) => {
|
connection.onMessage((data) => {
|
||||||
try {
|
try {
|
||||||
@ -89,7 +92,7 @@ export class Server {
|
|||||||
if (message.hasNewEval()) {
|
if (message.hasNewEval()) {
|
||||||
evaluate(this.connection, message.getNewEval()!);
|
evaluate(this.connection, message.getNewEval()!);
|
||||||
} else if (message.hasNewSession()) {
|
} else if (message.hasNewSession()) {
|
||||||
const session = handleNewSession(this.connection, message.getNewSession()!, () => {
|
const session = handleNewSession(this.connection, message.getNewSession()!, this.options, () => {
|
||||||
this.sessions.delete(message.getNewSession()!.getId());
|
this.sessions.delete(message.getNewSession()!.getId());
|
||||||
});
|
});
|
||||||
this.sessions.set(message.getNewSession()!.getId(), session);
|
this.sessions.set(message.getNewSession()!.getId(), session);
|
||||||
|
@ -17,8 +17,6 @@ message ClientMessage {
|
|||||||
|
|
||||||
// node.proto
|
// node.proto
|
||||||
NewEvalMessage new_eval = 9;
|
NewEvalMessage new_eval = 9;
|
||||||
|
|
||||||
SharedProcessInitMessage shared_process_init = 10;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +37,9 @@ message ServerMessage {
|
|||||||
EvalDoneMessage eval_done = 10;
|
EvalDoneMessage eval_done = 10;
|
||||||
|
|
||||||
WorkingInitMessage init = 11;
|
WorkingInitMessage init = 11;
|
||||||
|
|
||||||
|
// vscode.proto
|
||||||
|
SharedProcessActiveMessage shared_process_active = 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
packages/protocol/src/proto/client_pb.d.ts
vendored
14
packages/protocol/src/proto/client_pb.d.ts
vendored
@ -52,11 +52,6 @@ export class ClientMessage extends jspb.Message {
|
|||||||
getNewEval(): node_pb.NewEvalMessage | undefined;
|
getNewEval(): node_pb.NewEvalMessage | undefined;
|
||||||
setNewEval(value?: node_pb.NewEvalMessage): void;
|
setNewEval(value?: node_pb.NewEvalMessage): void;
|
||||||
|
|
||||||
hasSharedProcessInit(): boolean;
|
|
||||||
clearSharedProcessInit(): void;
|
|
||||||
getSharedProcessInit(): vscode_pb.SharedProcessInitMessage | undefined;
|
|
||||||
setSharedProcessInit(value?: vscode_pb.SharedProcessInitMessage): void;
|
|
||||||
|
|
||||||
getMsgCase(): ClientMessage.MsgCase;
|
getMsgCase(): ClientMessage.MsgCase;
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): ClientMessage.AsObject;
|
toObject(includeInstance?: boolean): ClientMessage.AsObject;
|
||||||
@ -79,7 +74,6 @@ export namespace ClientMessage {
|
|||||||
connectionOutput?: command_pb.ConnectionOutputMessage.AsObject,
|
connectionOutput?: command_pb.ConnectionOutputMessage.AsObject,
|
||||||
connectionClose?: command_pb.ConnectionCloseMessage.AsObject,
|
connectionClose?: command_pb.ConnectionCloseMessage.AsObject,
|
||||||
newEval?: node_pb.NewEvalMessage.AsObject,
|
newEval?: node_pb.NewEvalMessage.AsObject,
|
||||||
sharedProcessInit?: vscode_pb.SharedProcessInitMessage.AsObject,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MsgCase {
|
export enum MsgCase {
|
||||||
@ -93,7 +87,6 @@ export namespace ClientMessage {
|
|||||||
CONNECTION_OUTPUT = 7,
|
CONNECTION_OUTPUT = 7,
|
||||||
CONNECTION_CLOSE = 8,
|
CONNECTION_CLOSE = 8,
|
||||||
NEW_EVAL = 9,
|
NEW_EVAL = 9,
|
||||||
SHARED_PROCESS_INIT = 10,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +146,11 @@ export class ServerMessage extends jspb.Message {
|
|||||||
getInit(): WorkingInitMessage | undefined;
|
getInit(): WorkingInitMessage | undefined;
|
||||||
setInit(value?: WorkingInitMessage): void;
|
setInit(value?: WorkingInitMessage): void;
|
||||||
|
|
||||||
|
hasSharedProcessActive(): boolean;
|
||||||
|
clearSharedProcessActive(): void;
|
||||||
|
getSharedProcessActive(): vscode_pb.SharedProcessActiveMessage | undefined;
|
||||||
|
setSharedProcessActive(value?: vscode_pb.SharedProcessActiveMessage): void;
|
||||||
|
|
||||||
getMsgCase(): ServerMessage.MsgCase;
|
getMsgCase(): ServerMessage.MsgCase;
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): ServerMessage.AsObject;
|
toObject(includeInstance?: boolean): ServerMessage.AsObject;
|
||||||
@ -177,6 +175,7 @@ export namespace ServerMessage {
|
|||||||
evalFailed?: node_pb.EvalFailedMessage.AsObject,
|
evalFailed?: node_pb.EvalFailedMessage.AsObject,
|
||||||
evalDone?: node_pb.EvalDoneMessage.AsObject,
|
evalDone?: node_pb.EvalDoneMessage.AsObject,
|
||||||
init?: WorkingInitMessage.AsObject,
|
init?: WorkingInitMessage.AsObject,
|
||||||
|
sharedProcessActive?: vscode_pb.SharedProcessActiveMessage.AsObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MsgCase {
|
export enum MsgCase {
|
||||||
@ -192,6 +191,7 @@ export namespace ServerMessage {
|
|||||||
EVAL_FAILED = 9,
|
EVAL_FAILED = 9,
|
||||||
EVAL_DONE = 10,
|
EVAL_DONE = 10,
|
||||||
INIT = 11,
|
INIT = 11,
|
||||||
|
SHARED_PROCESS_ACTIVE = 12,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ if (goog.DEBUG && !COMPILED) {
|
|||||||
* @private {!Array<!Array<number>>}
|
* @private {!Array<!Array<number>>}
|
||||||
* @const
|
* @const
|
||||||
*/
|
*/
|
||||||
proto.ClientMessage.oneofGroups_ = [[1,2,3,4,5,6,7,8,9,10]];
|
proto.ClientMessage.oneofGroups_ = [[1,2,3,4,5,6,7,8,9]];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
@ -57,8 +57,7 @@ proto.ClientMessage.MsgCase = {
|
|||||||
NEW_CONNECTION: 6,
|
NEW_CONNECTION: 6,
|
||||||
CONNECTION_OUTPUT: 7,
|
CONNECTION_OUTPUT: 7,
|
||||||
CONNECTION_CLOSE: 8,
|
CONNECTION_CLOSE: 8,
|
||||||
NEW_EVAL: 9,
|
NEW_EVAL: 9
|
||||||
SHARED_PROCESS_INIT: 10
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,8 +103,7 @@ proto.ClientMessage.toObject = function(includeInstance, msg) {
|
|||||||
newConnection: (f = msg.getNewConnection()) && command_pb.NewConnectionMessage.toObject(includeInstance, f),
|
newConnection: (f = msg.getNewConnection()) && command_pb.NewConnectionMessage.toObject(includeInstance, f),
|
||||||
connectionOutput: (f = msg.getConnectionOutput()) && command_pb.ConnectionOutputMessage.toObject(includeInstance, f),
|
connectionOutput: (f = msg.getConnectionOutput()) && command_pb.ConnectionOutputMessage.toObject(includeInstance, f),
|
||||||
connectionClose: (f = msg.getConnectionClose()) && command_pb.ConnectionCloseMessage.toObject(includeInstance, f),
|
connectionClose: (f = msg.getConnectionClose()) && command_pb.ConnectionCloseMessage.toObject(includeInstance, f),
|
||||||
newEval: (f = msg.getNewEval()) && node_pb.NewEvalMessage.toObject(includeInstance, f),
|
newEval: (f = msg.getNewEval()) && node_pb.NewEvalMessage.toObject(includeInstance, f)
|
||||||
sharedProcessInit: (f = msg.getSharedProcessInit()) && vscode_pb.SharedProcessInitMessage.toObject(includeInstance, f)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -187,11 +185,6 @@ proto.ClientMessage.deserializeBinaryFromReader = function(msg, reader) {
|
|||||||
reader.readMessage(value,node_pb.NewEvalMessage.deserializeBinaryFromReader);
|
reader.readMessage(value,node_pb.NewEvalMessage.deserializeBinaryFromReader);
|
||||||
msg.setNewEval(value);
|
msg.setNewEval(value);
|
||||||
break;
|
break;
|
||||||
case 10:
|
|
||||||
var value = new vscode_pb.SharedProcessInitMessage;
|
|
||||||
reader.readMessage(value,vscode_pb.SharedProcessInitMessage.deserializeBinaryFromReader);
|
|
||||||
msg.setSharedProcessInit(value);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
break;
|
break;
|
||||||
@ -302,14 +295,6 @@ proto.ClientMessage.prototype.serializeBinaryToWriter = function (writer) {
|
|||||||
node_pb.NewEvalMessage.serializeBinaryToWriter
|
node_pb.NewEvalMessage.serializeBinaryToWriter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
f = this.getSharedProcessInit();
|
|
||||||
if (f != null) {
|
|
||||||
writer.writeMessage(
|
|
||||||
10,
|
|
||||||
f,
|
|
||||||
vscode_pb.SharedProcessInitMessage.serializeBinaryToWriter
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -592,36 +577,6 @@ proto.ClientMessage.prototype.hasNewEval = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* optional SharedProcessInitMessage shared_process_init = 10;
|
|
||||||
* @return {proto.SharedProcessInitMessage}
|
|
||||||
*/
|
|
||||||
proto.ClientMessage.prototype.getSharedProcessInit = function() {
|
|
||||||
return /** @type{proto.SharedProcessInitMessage} */ (
|
|
||||||
jspb.Message.getWrapperField(this, vscode_pb.SharedProcessInitMessage, 10));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @param {proto.SharedProcessInitMessage|undefined} value */
|
|
||||||
proto.ClientMessage.prototype.setSharedProcessInit = function(value) {
|
|
||||||
jspb.Message.setOneofWrapperField(this, 10, proto.ClientMessage.oneofGroups_[0], value);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
proto.ClientMessage.prototype.clearSharedProcessInit = function() {
|
|
||||||
this.setSharedProcessInit(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether this field is set.
|
|
||||||
* @return{!boolean}
|
|
||||||
*/
|
|
||||||
proto.ClientMessage.prototype.hasSharedProcessInit = function() {
|
|
||||||
return jspb.Message.getField(this, 10) != null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated by JsPbCodeGenerator.
|
* Generated by JsPbCodeGenerator.
|
||||||
@ -648,7 +603,7 @@ if (goog.DEBUG && !COMPILED) {
|
|||||||
* @private {!Array<!Array<number>>}
|
* @private {!Array<!Array<number>>}
|
||||||
* @const
|
* @const
|
||||||
*/
|
*/
|
||||||
proto.ServerMessage.oneofGroups_ = [[1,2,3,4,5,6,7,8,9,10,11]];
|
proto.ServerMessage.oneofGroups_ = [[1,2,3,4,5,6,7,8,9,10,11,12]];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum {number}
|
* @enum {number}
|
||||||
@ -665,7 +620,8 @@ proto.ServerMessage.MsgCase = {
|
|||||||
CONNECTION_ESTABLISHED: 8,
|
CONNECTION_ESTABLISHED: 8,
|
||||||
EVAL_FAILED: 9,
|
EVAL_FAILED: 9,
|
||||||
EVAL_DONE: 10,
|
EVAL_DONE: 10,
|
||||||
INIT: 11
|
INIT: 11,
|
||||||
|
SHARED_PROCESS_ACTIVE: 12
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -713,7 +669,8 @@ proto.ServerMessage.toObject = function(includeInstance, msg) {
|
|||||||
connectionEstablished: (f = msg.getConnectionEstablished()) && command_pb.ConnectionEstablishedMessage.toObject(includeInstance, f),
|
connectionEstablished: (f = msg.getConnectionEstablished()) && command_pb.ConnectionEstablishedMessage.toObject(includeInstance, f),
|
||||||
evalFailed: (f = msg.getEvalFailed()) && node_pb.EvalFailedMessage.toObject(includeInstance, f),
|
evalFailed: (f = msg.getEvalFailed()) && node_pb.EvalFailedMessage.toObject(includeInstance, f),
|
||||||
evalDone: (f = msg.getEvalDone()) && node_pb.EvalDoneMessage.toObject(includeInstance, f),
|
evalDone: (f = msg.getEvalDone()) && node_pb.EvalDoneMessage.toObject(includeInstance, f),
|
||||||
init: (f = msg.getInit()) && proto.WorkingInitMessage.toObject(includeInstance, f)
|
init: (f = msg.getInit()) && proto.WorkingInitMessage.toObject(includeInstance, f),
|
||||||
|
sharedProcessActive: (f = msg.getSharedProcessActive()) && vscode_pb.SharedProcessActiveMessage.toObject(includeInstance, f)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -805,6 +762,11 @@ proto.ServerMessage.deserializeBinaryFromReader = function(msg, reader) {
|
|||||||
reader.readMessage(value,proto.WorkingInitMessage.deserializeBinaryFromReader);
|
reader.readMessage(value,proto.WorkingInitMessage.deserializeBinaryFromReader);
|
||||||
msg.setInit(value);
|
msg.setInit(value);
|
||||||
break;
|
break;
|
||||||
|
case 12:
|
||||||
|
var value = new vscode_pb.SharedProcessActiveMessage;
|
||||||
|
reader.readMessage(value,vscode_pb.SharedProcessActiveMessage.deserializeBinaryFromReader);
|
||||||
|
msg.setSharedProcessActive(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
break;
|
break;
|
||||||
@ -931,6 +893,14 @@ proto.ServerMessage.prototype.serializeBinaryToWriter = function (writer) {
|
|||||||
proto.WorkingInitMessage.serializeBinaryToWriter
|
proto.WorkingInitMessage.serializeBinaryToWriter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
f = this.getSharedProcessActive();
|
||||||
|
if (f != null) {
|
||||||
|
writer.writeMessage(
|
||||||
|
12,
|
||||||
|
f,
|
||||||
|
vscode_pb.SharedProcessActiveMessage.serializeBinaryToWriter
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1273,6 +1243,36 @@ proto.ServerMessage.prototype.hasInit = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional SharedProcessActiveMessage shared_process_active = 12;
|
||||||
|
* @return {proto.SharedProcessActiveMessage}
|
||||||
|
*/
|
||||||
|
proto.ServerMessage.prototype.getSharedProcessActive = function() {
|
||||||
|
return /** @type{proto.SharedProcessActiveMessage} */ (
|
||||||
|
jspb.Message.getWrapperField(this, vscode_pb.SharedProcessActiveMessage, 12));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** @param {proto.SharedProcessActiveMessage|undefined} value */
|
||||||
|
proto.ServerMessage.prototype.setSharedProcessActive = function(value) {
|
||||||
|
jspb.Message.setOneofWrapperField(this, 12, proto.ServerMessage.oneofGroups_[0], value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
proto.ServerMessage.prototype.clearSharedProcessActive = function() {
|
||||||
|
this.setSharedProcessActive(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this field is set.
|
||||||
|
* @return{!boolean}
|
||||||
|
*/
|
||||||
|
proto.ServerMessage.prototype.hasSharedProcessActive = function() {
|
||||||
|
return jspb.Message.getField(this, 12) != null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated by JsPbCodeGenerator.
|
* Generated by JsPbCodeGenerator.
|
||||||
|
@ -13,6 +13,9 @@ message NewSessionMessage {
|
|||||||
string cwd = 5;
|
string cwd = 5;
|
||||||
TTYDimensions tty_dimensions = 6;
|
TTYDimensions tty_dimensions = 6;
|
||||||
bool is_fork = 7;
|
bool is_fork = 7;
|
||||||
|
|
||||||
|
// Janky, but required for having custom handling of the bootstrap fork
|
||||||
|
bool is_bootstrap_fork = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sent when starting a session failed.
|
// Sent when starting a session failed.
|
||||||
|
4
packages/protocol/src/proto/command_pb.d.ts
vendored
4
packages/protocol/src/proto/command_pb.d.ts
vendored
@ -28,6 +28,9 @@ export class NewSessionMessage extends jspb.Message {
|
|||||||
getIsFork(): boolean;
|
getIsFork(): boolean;
|
||||||
setIsFork(value: boolean): void;
|
setIsFork(value: boolean): void;
|
||||||
|
|
||||||
|
getIsBootstrapFork(): boolean;
|
||||||
|
setIsBootstrapFork(value: boolean): void;
|
||||||
|
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): NewSessionMessage.AsObject;
|
toObject(includeInstance?: boolean): NewSessionMessage.AsObject;
|
||||||
static toObject(includeInstance: boolean, msg: NewSessionMessage): NewSessionMessage.AsObject;
|
static toObject(includeInstance: boolean, msg: NewSessionMessage): NewSessionMessage.AsObject;
|
||||||
@ -47,6 +50,7 @@ export namespace NewSessionMessage {
|
|||||||
cwd: string,
|
cwd: string,
|
||||||
ttyDimensions?: TTYDimensions.AsObject,
|
ttyDimensions?: TTYDimensions.AsObject,
|
||||||
isFork: boolean,
|
isFork: boolean,
|
||||||
|
isBootstrapFork: boolean,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,8 @@ proto.NewSessionMessage.toObject = function(includeInstance, msg) {
|
|||||||
envMap: (f = msg.getEnvMap(true)) ? f.toArray() : [],
|
envMap: (f = msg.getEnvMap(true)) ? f.toArray() : [],
|
||||||
cwd: msg.getCwd(),
|
cwd: msg.getCwd(),
|
||||||
ttyDimensions: (f = msg.getTtyDimensions()) && proto.TTYDimensions.toObject(includeInstance, f),
|
ttyDimensions: (f = msg.getTtyDimensions()) && proto.TTYDimensions.toObject(includeInstance, f),
|
||||||
isFork: msg.getIsFork()
|
isFork: msg.getIsFork(),
|
||||||
|
isBootstrapFork: msg.getIsBootstrapFork()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -154,6 +155,10 @@ proto.NewSessionMessage.deserializeBinaryFromReader = function(msg, reader) {
|
|||||||
var value = /** @type {boolean} */ (reader.readBool());
|
var value = /** @type {boolean} */ (reader.readBool());
|
||||||
msg.setIsFork(value);
|
msg.setIsFork(value);
|
||||||
break;
|
break;
|
||||||
|
case 8:
|
||||||
|
var value = /** @type {boolean} */ (reader.readBool());
|
||||||
|
msg.setIsBootstrapFork(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
break;
|
break;
|
||||||
@ -239,6 +244,13 @@ proto.NewSessionMessage.prototype.serializeBinaryToWriter = function (writer) {
|
|||||||
f
|
f
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
f = this.getIsBootstrapFork();
|
||||||
|
if (f) {
|
||||||
|
writer.writeBool(
|
||||||
|
8,
|
||||||
|
f
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -378,6 +390,23 @@ proto.NewSessionMessage.prototype.setIsFork = function(value) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* optional bool is_bootstrap_fork = 8;
|
||||||
|
* Note that Boolean fields may be set to 0/1 when serialized from a Java server.
|
||||||
|
* You should avoid comparisons like {@code val === true/false} in those cases.
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
proto.NewSessionMessage.prototype.getIsBootstrapFork = function() {
|
||||||
|
return /** @type {boolean} */ (jspb.Message.getFieldProto3(this, 8, false));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** @param {boolean} value */
|
||||||
|
proto.NewSessionMessage.prototype.setIsBootstrapFork = function(value) {
|
||||||
|
jspb.Message.setField(this, 8, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated by JsPbCodeGenerator.
|
* Generated by JsPbCodeGenerator.
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
message SharedProcessInitMessage {
|
// Sent when a shared process becomes active
|
||||||
uint64 window_id = 1;
|
message SharedProcessActiveMessage {
|
||||||
string log_directory = 2;
|
string socket_path = 1;
|
||||||
|
|
||||||
// Maps to `"vs/platform/log/common/log".LogLevel`
|
|
||||||
uint32 log_level = 3;
|
|
||||||
}
|
}
|
28
packages/protocol/src/proto/vscode_pb.d.ts
vendored
28
packages/protocol/src/proto/vscode_pb.d.ts
vendored
@ -3,31 +3,23 @@
|
|||||||
|
|
||||||
import * as jspb from "google-protobuf";
|
import * as jspb from "google-protobuf";
|
||||||
|
|
||||||
export class SharedProcessInitMessage extends jspb.Message {
|
export class SharedProcessActiveMessage extends jspb.Message {
|
||||||
getWindowId(): number;
|
getSocketPath(): string;
|
||||||
setWindowId(value: number): void;
|
setSocketPath(value: string): void;
|
||||||
|
|
||||||
getLogDirectory(): string;
|
|
||||||
setLogDirectory(value: string): void;
|
|
||||||
|
|
||||||
getLogLevel(): number;
|
|
||||||
setLogLevel(value: number): void;
|
|
||||||
|
|
||||||
serializeBinary(): Uint8Array;
|
serializeBinary(): Uint8Array;
|
||||||
toObject(includeInstance?: boolean): SharedProcessInitMessage.AsObject;
|
toObject(includeInstance?: boolean): SharedProcessActiveMessage.AsObject;
|
||||||
static toObject(includeInstance: boolean, msg: SharedProcessInitMessage): SharedProcessInitMessage.AsObject;
|
static toObject(includeInstance: boolean, msg: SharedProcessActiveMessage): SharedProcessActiveMessage.AsObject;
|
||||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||||
static serializeBinaryToWriter(message: SharedProcessInitMessage, writer: jspb.BinaryWriter): void;
|
static serializeBinaryToWriter(message: SharedProcessActiveMessage, writer: jspb.BinaryWriter): void;
|
||||||
static deserializeBinary(bytes: Uint8Array): SharedProcessInitMessage;
|
static deserializeBinary(bytes: Uint8Array): SharedProcessActiveMessage;
|
||||||
static deserializeBinaryFromReader(message: SharedProcessInitMessage, reader: jspb.BinaryReader): SharedProcessInitMessage;
|
static deserializeBinaryFromReader(message: SharedProcessActiveMessage, reader: jspb.BinaryReader): SharedProcessActiveMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace SharedProcessInitMessage {
|
export namespace SharedProcessActiveMessage {
|
||||||
export type AsObject = {
|
export type AsObject = {
|
||||||
windowId: number,
|
socketPath: string,
|
||||||
logDirectory: string,
|
|
||||||
logLevel: number,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ var jspb = require('google-protobuf');
|
|||||||
var goog = jspb;
|
var goog = jspb;
|
||||||
var global = Function('return this')();
|
var global = Function('return this')();
|
||||||
|
|
||||||
goog.exportSymbol('proto.SharedProcessInitMessage', null, global);
|
goog.exportSymbol('proto.SharedProcessActiveMessage', null, global);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generated by JsPbCodeGenerator.
|
* Generated by JsPbCodeGenerator.
|
||||||
@ -21,12 +21,12 @@ goog.exportSymbol('proto.SharedProcessInitMessage', null, global);
|
|||||||
* @extends {jspb.Message}
|
* @extends {jspb.Message}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage = function(opt_data) {
|
proto.SharedProcessActiveMessage = function(opt_data) {
|
||||||
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
|
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
|
||||||
};
|
};
|
||||||
goog.inherits(proto.SharedProcessInitMessage, jspb.Message);
|
goog.inherits(proto.SharedProcessActiveMessage, jspb.Message);
|
||||||
if (goog.DEBUG && !COMPILED) {
|
if (goog.DEBUG && !COMPILED) {
|
||||||
proto.SharedProcessInitMessage.displayName = 'proto.SharedProcessInitMessage';
|
proto.SharedProcessActiveMessage.displayName = 'proto.SharedProcessActiveMessage';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -41,8 +41,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) {
|
|||||||
* for transitional soy proto support: http://goto/soy-param-migration
|
* for transitional soy proto support: http://goto/soy-param-migration
|
||||||
* @return {!Object}
|
* @return {!Object}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.prototype.toObject = function(opt_includeInstance) {
|
proto.SharedProcessActiveMessage.prototype.toObject = function(opt_includeInstance) {
|
||||||
return proto.SharedProcessInitMessage.toObject(opt_includeInstance, this);
|
return proto.SharedProcessActiveMessage.toObject(opt_includeInstance, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -51,14 +51,12 @@ proto.SharedProcessInitMessage.prototype.toObject = function(opt_includeInstance
|
|||||||
* @param {boolean|undefined} includeInstance Whether to include the JSPB
|
* @param {boolean|undefined} includeInstance Whether to include the JSPB
|
||||||
* instance for transitional soy proto support:
|
* instance for transitional soy proto support:
|
||||||
* http://goto/soy-param-migration
|
* http://goto/soy-param-migration
|
||||||
* @param {!proto.SharedProcessInitMessage} msg The msg instance to transform.
|
* @param {!proto.SharedProcessActiveMessage} msg The msg instance to transform.
|
||||||
* @return {!Object}
|
* @return {!Object}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.toObject = function(includeInstance, msg) {
|
proto.SharedProcessActiveMessage.toObject = function(includeInstance, msg) {
|
||||||
var f, obj = {
|
var f, obj = {
|
||||||
windowId: msg.getWindowId(),
|
socketPath: msg.getSocketPath()
|
||||||
logDirectory: msg.getLogDirectory(),
|
|
||||||
logLevel: msg.getLogLevel()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (includeInstance) {
|
if (includeInstance) {
|
||||||
@ -72,23 +70,23 @@ proto.SharedProcessInitMessage.toObject = function(includeInstance, msg) {
|
|||||||
/**
|
/**
|
||||||
* Deserializes binary data (in protobuf wire format).
|
* Deserializes binary data (in protobuf wire format).
|
||||||
* @param {jspb.ByteSource} bytes The bytes to deserialize.
|
* @param {jspb.ByteSource} bytes The bytes to deserialize.
|
||||||
* @return {!proto.SharedProcessInitMessage}
|
* @return {!proto.SharedProcessActiveMessage}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.deserializeBinary = function(bytes) {
|
proto.SharedProcessActiveMessage.deserializeBinary = function(bytes) {
|
||||||
var reader = new jspb.BinaryReader(bytes);
|
var reader = new jspb.BinaryReader(bytes);
|
||||||
var msg = new proto.SharedProcessInitMessage;
|
var msg = new proto.SharedProcessActiveMessage;
|
||||||
return proto.SharedProcessInitMessage.deserializeBinaryFromReader(msg, reader);
|
return proto.SharedProcessActiveMessage.deserializeBinaryFromReader(msg, reader);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserializes binary data (in protobuf wire format) from the
|
* Deserializes binary data (in protobuf wire format) from the
|
||||||
* given reader into the given message object.
|
* given reader into the given message object.
|
||||||
* @param {!proto.SharedProcessInitMessage} msg The message object to deserialize into.
|
* @param {!proto.SharedProcessActiveMessage} msg The message object to deserialize into.
|
||||||
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
|
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
|
||||||
* @return {!proto.SharedProcessInitMessage}
|
* @return {!proto.SharedProcessActiveMessage}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.deserializeBinaryFromReader = function(msg, reader) {
|
proto.SharedProcessActiveMessage.deserializeBinaryFromReader = function(msg, reader) {
|
||||||
while (reader.nextField()) {
|
while (reader.nextField()) {
|
||||||
if (reader.isEndGroup()) {
|
if (reader.isEndGroup()) {
|
||||||
break;
|
break;
|
||||||
@ -96,16 +94,8 @@ proto.SharedProcessInitMessage.deserializeBinaryFromReader = function(msg, reade
|
|||||||
var field = reader.getFieldNumber();
|
var field = reader.getFieldNumber();
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 1:
|
case 1:
|
||||||
var value = /** @type {number} */ (reader.readUint64());
|
|
||||||
msg.setWindowId(value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
var value = /** @type {string} */ (reader.readString());
|
var value = /** @type {string} */ (reader.readString());
|
||||||
msg.setLogDirectory(value);
|
msg.setSocketPath(value);
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
var value = /** @type {number} */ (reader.readUint32());
|
|
||||||
msg.setLogLevel(value);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reader.skipField();
|
reader.skipField();
|
||||||
@ -119,10 +109,10 @@ proto.SharedProcessInitMessage.deserializeBinaryFromReader = function(msg, reade
|
|||||||
/**
|
/**
|
||||||
* Class method variant: serializes the given message to binary data
|
* Class method variant: serializes the given message to binary data
|
||||||
* (in protobuf wire format), writing to the given BinaryWriter.
|
* (in protobuf wire format), writing to the given BinaryWriter.
|
||||||
* @param {!proto.SharedProcessInitMessage} message
|
* @param {!proto.SharedProcessActiveMessage} message
|
||||||
* @param {!jspb.BinaryWriter} writer
|
* @param {!jspb.BinaryWriter} writer
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.serializeBinaryToWriter = function(message, writer) {
|
proto.SharedProcessActiveMessage.serializeBinaryToWriter = function(message, writer) {
|
||||||
message.serializeBinaryToWriter(writer);
|
message.serializeBinaryToWriter(writer);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -131,7 +121,7 @@ proto.SharedProcessInitMessage.serializeBinaryToWriter = function(message, write
|
|||||||
* Serializes the message to binary data (in protobuf wire format).
|
* Serializes the message to binary data (in protobuf wire format).
|
||||||
* @return {!Uint8Array}
|
* @return {!Uint8Array}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.prototype.serializeBinary = function() {
|
proto.SharedProcessActiveMessage.prototype.serializeBinary = function() {
|
||||||
var writer = new jspb.BinaryWriter();
|
var writer = new jspb.BinaryWriter();
|
||||||
this.serializeBinaryToWriter(writer);
|
this.serializeBinaryToWriter(writer);
|
||||||
return writer.getResultBuffer();
|
return writer.getResultBuffer();
|
||||||
@ -143,26 +133,12 @@ proto.SharedProcessInitMessage.prototype.serializeBinary = function() {
|
|||||||
* writing to the given BinaryWriter.
|
* writing to the given BinaryWriter.
|
||||||
* @param {!jspb.BinaryWriter} writer
|
* @param {!jspb.BinaryWriter} writer
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.prototype.serializeBinaryToWriter = function (writer) {
|
proto.SharedProcessActiveMessage.prototype.serializeBinaryToWriter = function (writer) {
|
||||||
var f = undefined;
|
var f = undefined;
|
||||||
f = this.getWindowId();
|
f = this.getSocketPath();
|
||||||
if (f !== 0) {
|
|
||||||
writer.writeUint64(
|
|
||||||
1,
|
|
||||||
f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
f = this.getLogDirectory();
|
|
||||||
if (f.length > 0) {
|
if (f.length > 0) {
|
||||||
writer.writeString(
|
writer.writeString(
|
||||||
2,
|
1,
|
||||||
f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
f = this.getLogLevel();
|
|
||||||
if (f !== 0) {
|
|
||||||
writer.writeUint32(
|
|
||||||
3,
|
|
||||||
f
|
f
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -171,55 +147,25 @@ proto.SharedProcessInitMessage.prototype.serializeBinaryToWriter = function (wri
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a deep clone of this proto. No data is shared with the original.
|
* Creates a deep clone of this proto. No data is shared with the original.
|
||||||
* @return {!proto.SharedProcessInitMessage} The clone.
|
* @return {!proto.SharedProcessActiveMessage} The clone.
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.prototype.cloneMessage = function() {
|
proto.SharedProcessActiveMessage.prototype.cloneMessage = function() {
|
||||||
return /** @type {!proto.SharedProcessInitMessage} */ (jspb.Message.cloneMessage(this));
|
return /** @type {!proto.SharedProcessActiveMessage} */ (jspb.Message.cloneMessage(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* optional uint64 window_id = 1;
|
* optional string socket_path = 1;
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
proto.SharedProcessInitMessage.prototype.getWindowId = function() {
|
|
||||||
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @param {number} value */
|
|
||||||
proto.SharedProcessInitMessage.prototype.setWindowId = function(value) {
|
|
||||||
jspb.Message.setField(this, 1, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* optional string log_directory = 2;
|
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
proto.SharedProcessInitMessage.prototype.getLogDirectory = function() {
|
proto.SharedProcessActiveMessage.prototype.getSocketPath = function() {
|
||||||
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 2, ""));
|
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** @param {string} value */
|
/** @param {string} value */
|
||||||
proto.SharedProcessInitMessage.prototype.setLogDirectory = function(value) {
|
proto.SharedProcessActiveMessage.prototype.setSocketPath = function(value) {
|
||||||
jspb.Message.setField(this, 2, value);
|
jspb.Message.setField(this, 1, value);
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* optional uint32 log_level = 3;
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
proto.SharedProcessInitMessage.prototype.getLogLevel = function() {
|
|
||||||
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 3, 0));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @param {number} value */
|
|
||||||
proto.SharedProcessInitMessage.prototype.setLogLevel = function(value) {
|
|
||||||
jspb.Message.setField(this, 3, value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { SharedProcessInitMessage } from "@coder/protocol/src/proto";
|
import { field, logger } from "@coder/logger";
|
||||||
|
import { ServerMessage, SharedProcessActiveMessage } from "@coder/protocol/src/proto";
|
||||||
import { Command, flags } from "@oclif/command";
|
import { Command, flags } from "@oclif/command";
|
||||||
import { logger, field } from "@coder/logger";
|
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { requireModule } from "./vscode/bootstrapFork";
|
import * as WebSocket from "ws";
|
||||||
import { createApp } from "./server";
|
import { createApp } from "./server";
|
||||||
import { SharedProcess } from './vscode/sharedProcess';
|
import { requireModule } from "./vscode/bootstrapFork";
|
||||||
|
import { SharedProcess, SharedProcessState } from './vscode/sharedProcess';
|
||||||
|
|
||||||
export class Entry extends Command {
|
export class Entry extends Command {
|
||||||
|
|
||||||
@ -69,15 +70,22 @@ export class Entry extends Command {
|
|||||||
logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir));
|
logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir));
|
||||||
const sharedProcess = new SharedProcess(dataDir);
|
const sharedProcess = new SharedProcess(dataDir);
|
||||||
logger.info("Starting shared process...", field("socket", sharedProcess.socketPath));
|
logger.info("Starting shared process...", field("socket", sharedProcess.socketPath));
|
||||||
sharedProcess.onWillRestart(() => {
|
const sendSharedProcessReady = (socket: WebSocket) => {
|
||||||
logger.info("Restarting shared process...");
|
const active = new SharedProcessActiveMessage();
|
||||||
|
active.setSocketPath(sharedProcess.socketPath);
|
||||||
sharedProcess.ready.then(() => {
|
const serverMessage = new ServerMessage();
|
||||||
logger.info("Shared process has restarted!");
|
serverMessage.setSharedProcessActive(active);
|
||||||
});
|
socket.send(serverMessage.serializeBinary());
|
||||||
});
|
};
|
||||||
sharedProcess.ready.then(() => {
|
sharedProcess.onState((event) => {
|
||||||
logger.info("Shared process has started up!");
|
if (event.state === SharedProcessState.Stopped) {
|
||||||
|
logger.error("Shared process stopped. Restarting...", field("error", event.error));
|
||||||
|
} else if (event.state === SharedProcessState.Starting) {
|
||||||
|
logger.info("Starting shared process...");
|
||||||
|
} else if (event.state === SharedProcessState.Ready) {
|
||||||
|
logger.info("Shared process is ready!");
|
||||||
|
app.wss.clients.forEach((c) => sendSharedProcessReady(c));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = createApp((app) => {
|
const app = createApp((app) => {
|
||||||
@ -108,13 +116,12 @@ export class Entry extends Command {
|
|||||||
let clientId = 1;
|
let clientId = 1;
|
||||||
app.wss.on("connection", (ws, req) => {
|
app.wss.on("connection", (ws, req) => {
|
||||||
const id = clientId++;
|
const id = clientId++;
|
||||||
const spm = (<any>req).sharedProcessInit as SharedProcessInitMessage;
|
|
||||||
if (!spm) {
|
|
||||||
logger.warn("Received a socket without init data. Not sure how this happened.");
|
|
||||||
|
|
||||||
return;
|
if (sharedProcess.state === SharedProcessState.Ready) {
|
||||||
|
sendSharedProcessReady(ws);
|
||||||
}
|
}
|
||||||
logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress), field("window_id", spm.getWindowId()), field("log_directory", spm.getLogDirectory()));
|
|
||||||
|
logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress));
|
||||||
|
|
||||||
ws.on("close", (code) => {
|
ws.on("close", (code) => {
|
||||||
logger.info(`WebSocket closed \u001B[0m${req.url}`, field("client", id), field("code", code));
|
logger.info(`WebSocket closed \u001B[0m${req.url}`, field("client", id), field("code", code));
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { ReadWriteConnection } from "@coder/protocol";
|
import { ReadWriteConnection } from "@coder/protocol";
|
||||||
import { Server, ServerOptions } from "@coder/protocol/src/node/server";
|
import { Server, ServerOptions } from "@coder/protocol/src/node/server";
|
||||||
|
import { NewSessionMessage } from '@coder/protocol/src/proto';
|
||||||
|
import { ChildProcess } from "child_process";
|
||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
import * as http from "http";
|
import * as http from "http";
|
||||||
import * as ws from "ws";
|
import * as ws from "ws";
|
||||||
import * as url from "url";
|
import { forkModule } from "./vscode/bootstrapFork";
|
||||||
import { ClientMessage, SharedProcessInitMessage } from '@coder/protocol/src/proto';
|
|
||||||
|
|
||||||
export const createApp = (registerMiddleware?: (app: express.Application) => void, options?: ServerOptions): {
|
export const createApp = (registerMiddleware?: (app: express.Application) => void, options?: ServerOptions): {
|
||||||
readonly express: express.Application;
|
readonly express: express.Application;
|
||||||
@ -19,27 +20,7 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
|||||||
const wss = new ws.Server({ server });
|
const wss = new ws.Server({ server });
|
||||||
|
|
||||||
wss.shouldHandle = (req): boolean => {
|
wss.shouldHandle = (req): boolean => {
|
||||||
if (typeof req.url === "undefined") {
|
// Should handle auth here
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedUrl = url.parse(req.url, true);
|
|
||||||
const sharedProcessInit = parsedUrl.query["shared_process_init"];
|
|
||||||
if (typeof sharedProcessInit === "undefined" || Array.isArray(sharedProcessInit)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const msg = ClientMessage.deserializeBinary(Buffer.from(sharedProcessInit, "base64"));
|
|
||||||
if (!msg.hasSharedProcessInit()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const spm = msg.getSharedProcessInit()!;
|
|
||||||
(<any>req).sharedProcessInit = spm;
|
|
||||||
} catch (ex) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,7 +40,20 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
|
|||||||
onClose: (cb): void => ws.addEventListener("close", () => cb()),
|
onClose: (cb): void => ws.addEventListener("close", () => cb()),
|
||||||
};
|
};
|
||||||
|
|
||||||
const server = new Server(connection, options);
|
const server = new Server(connection, options ? {
|
||||||
|
...options,
|
||||||
|
forkProvider: (message: NewSessionMessage): ChildProcess => {
|
||||||
|
let proc: ChildProcess;
|
||||||
|
|
||||||
|
if (message.getIsBootstrapFork()) {
|
||||||
|
proc = forkModule(message.getCommand());
|
||||||
|
} else {
|
||||||
|
throw new Error("No support for non bootstrap-forking yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc;
|
||||||
|
},
|
||||||
|
} : undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,41 +9,47 @@ import { ParsedArgs } from "vs/platform/environment/common/environment";
|
|||||||
import { LogLevel } from "vs/platform/log/common/log";
|
import { LogLevel } from "vs/platform/log/common/log";
|
||||||
import { Emitter, Event } from '@coder/events/src';
|
import { Emitter, Event } from '@coder/events/src';
|
||||||
|
|
||||||
|
export enum SharedProcessState {
|
||||||
|
Stopped,
|
||||||
|
Starting,
|
||||||
|
Ready,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SharedProcessEvent = {
|
||||||
|
readonly state: SharedProcessState.Ready | SharedProcessState.Starting;
|
||||||
|
} | {
|
||||||
|
readonly state: SharedProcessState.Stopped;
|
||||||
|
readonly error: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class SharedProcess {
|
export class SharedProcess {
|
||||||
public readonly socketPath: string = path.join(os.tmpdir(), `.vscode-online${Math.random().toString()}`);
|
public readonly socketPath: string = path.join(os.tmpdir(), `.vscode-online${Math.random().toString()}`);
|
||||||
private _ready: Promise<void> | undefined;
|
private _state: SharedProcessState = SharedProcessState.Stopped;
|
||||||
private activeProcess: ChildProcess | undefined;
|
private activeProcess: ChildProcess | undefined;
|
||||||
private ipcHandler: StdioIpcHandler | undefined;
|
private ipcHandler: StdioIpcHandler | undefined;
|
||||||
private readonly willRestartEmitter: Emitter<void>;
|
private readonly onStateEmitter: Emitter<SharedProcessEvent>;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly userDataDir: string,
|
private readonly userDataDir: string,
|
||||||
) {
|
) {
|
||||||
this.willRestartEmitter = new Emitter();
|
this.onStateEmitter = new Emitter();
|
||||||
|
|
||||||
this.restart();
|
this.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get onWillRestart(): Event<void> {
|
public get onState(): Event<SharedProcessEvent> {
|
||||||
return this.willRestartEmitter.event;
|
return this.onStateEmitter.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get ready(): Promise<void> {
|
public get state(): SharedProcessState {
|
||||||
return this._ready!;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public restart(): void {
|
public restart(): void {
|
||||||
if (this.activeProcess) {
|
|
||||||
this.willRestartEmitter.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.activeProcess && !this.activeProcess.killed) {
|
if (this.activeProcess && !this.activeProcess.killed) {
|
||||||
this.activeProcess.kill();
|
this.activeProcess.kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolve: () => void;
|
|
||||||
let reject: (err: Error) => void;
|
|
||||||
|
|
||||||
const extensionsDir = path.join(this.userDataDir, "extensions");
|
const extensionsDir = path.join(this.userDataDir, "extensions");
|
||||||
const mkdir = (dir: string): void => {
|
const mkdir = (dir: string): void => {
|
||||||
try {
|
try {
|
||||||
@ -57,14 +63,18 @@ export class SharedProcess {
|
|||||||
mkdir(this.userDataDir);
|
mkdir(this.userDataDir);
|
||||||
mkdir(extensionsDir);
|
mkdir(extensionsDir);
|
||||||
|
|
||||||
this._ready = new Promise<void>((res, rej) => {
|
this.setState({
|
||||||
resolve = res;
|
state: SharedProcessState.Starting,
|
||||||
reject = rej;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let resolved: boolean = false;
|
let resolved: boolean = false;
|
||||||
this.activeProcess = forkModule("vs/code/electron-browser/sharedProcess/sharedProcessMain");
|
this.activeProcess = forkModule("vs/code/electron-browser/sharedProcess/sharedProcessMain");
|
||||||
this.activeProcess.on("exit", () => {
|
this.activeProcess.on("exit", (err) => {
|
||||||
|
if (this._state !== SharedProcessState.Stopped) {
|
||||||
|
this.setState({
|
||||||
|
error: `Exited with ${err}`,
|
||||||
|
state: SharedProcessState.Stopped,
|
||||||
|
});
|
||||||
|
}
|
||||||
this.restart();
|
this.restart();
|
||||||
});
|
});
|
||||||
this.ipcHandler = new StdioIpcHandler(this.activeProcess);
|
this.ipcHandler = new StdioIpcHandler(this.activeProcess);
|
||||||
@ -86,11 +96,20 @@ export class SharedProcess {
|
|||||||
});
|
});
|
||||||
this.ipcHandler.once("handshake:im ready", () => {
|
this.ipcHandler.once("handshake:im ready", () => {
|
||||||
resolved = true;
|
resolved = true;
|
||||||
resolve();
|
this.setState({
|
||||||
|
state: SharedProcessState.Ready,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
this.activeProcess.stderr.on("data", (data) => {
|
this.activeProcess.stderr.on("data", (data) => {
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
reject(data.toString());
|
this.setState({
|
||||||
|
error: data.toString(),
|
||||||
|
state: SharedProcessState.Stopped,
|
||||||
|
});
|
||||||
|
if (!this.activeProcess) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.activeProcess.kill();
|
||||||
} else {
|
} else {
|
||||||
logger.named("SHRD PROC").debug("stderr", field("message", data.toString()));
|
logger.named("SHRD PROC").debug("stderr", field("message", data.toString()));
|
||||||
}
|
}
|
||||||
@ -103,4 +122,9 @@ export class SharedProcess {
|
|||||||
}
|
}
|
||||||
this.ipcHandler = undefined;
|
this.ipcHandler = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setState(event: SharedProcessEvent): void {
|
||||||
|
this._state = event.state;
|
||||||
|
this.onStateEmitter.emit(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user