Handle permessage-deflate on sockets
With this the extension host is working again.
This commit is contained in:
parent
150138e04b
commit
4d3d1b844d
|
@ -68,7 +68,7 @@ process.on('message', async (message: CodeServerMessage, socket) => {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'socket':
|
case 'socket':
|
||||||
vscode.handleWebSocket(socket, message.query);
|
vscode.handleWebSocket(socket, message.query, message.permessageDeflate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,7 @@ export type Query = { [key: string]: string | string[] | undefined | Query | Que
|
||||||
export interface SocketMessage {
|
export interface SocketMessage {
|
||||||
type: 'socket';
|
type: 'socket';
|
||||||
query: Query;
|
query: Query;
|
||||||
|
permessageDeflate: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CliMessage {
|
export interface CliMessage {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { FileAccess } from 'vs/base/common/network';
|
import { FileAccess } from 'vs/base/common/network';
|
||||||
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
|
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
|
||||||
import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
import { WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||||
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { getNlsConfiguration } from 'vs/server/node/nls';
|
import { getNlsConfiguration } from 'vs/server/node/nls';
|
||||||
import { Protocol } from 'vs/server/node/protocol';
|
import { Protocol } from 'vs/server/node/protocol';
|
||||||
|
@ -88,7 +88,7 @@ export class ExtensionHostConnection extends Connection {
|
||||||
private readonly logger: Logger;
|
private readonly logger: Logger;
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
locale:string, protocol: Protocol, buffer: VSBuffer, token: string,
|
locale: string, protocol: Protocol, buffer: VSBuffer, token: string,
|
||||||
private readonly environment: INativeEnvironmentService,
|
private readonly environment: INativeEnvironmentService,
|
||||||
) {
|
) {
|
||||||
super(protocol, token);
|
super(protocol, token);
|
||||||
|
@ -115,11 +115,18 @@ export class ExtensionHostConnection extends Connection {
|
||||||
private sendInitMessage(buffer: VSBuffer): void {
|
private sendInitMessage(buffer: VSBuffer): void {
|
||||||
const socket = this.protocol.getUnderlyingSocket();
|
const socket = this.protocol.getUnderlyingSocket();
|
||||||
socket.pause();
|
socket.pause();
|
||||||
|
|
||||||
|
const wrapperSocket = this.protocol.getSocket();
|
||||||
|
|
||||||
this.logger.trace('Sending socket');
|
this.logger.trace('Sending socket');
|
||||||
this.process!.send({ // Process must be set at this point.
|
this.process!.send({ // Process must be set at this point.
|
||||||
type: 'VSCODE_EXTHOST_IPC_SOCKET',
|
type: 'VSCODE_EXTHOST_IPC_SOCKET',
|
||||||
initialDataChunk: (buffer.buffer as Buffer).toString('base64'),
|
initialDataChunk: Buffer.from(buffer.buffer).toString('base64'),
|
||||||
skipWebSocketFrames: this.protocol.getSocket() instanceof NodeSocket,
|
skipWebSocketFrames: !(wrapperSocket instanceof WebSocketNodeSocket),
|
||||||
|
permessageDeflate: this.protocol.options.permessageDeflate,
|
||||||
|
inflateBytes: wrapperSocket instanceof WebSocketNodeSocket
|
||||||
|
? Buffer.from(wrapperSocket.recordedInflateBytes.buffer).toString('base64')
|
||||||
|
: undefined,
|
||||||
}, socket);
|
}, socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,9 @@ export interface SocketOptions {
|
||||||
readonly reconnectionToken: string;
|
readonly reconnectionToken: string;
|
||||||
readonly reconnection: boolean;
|
readonly reconnection: boolean;
|
||||||
readonly skipWebSocketFrames: boolean;
|
readonly skipWebSocketFrames: boolean;
|
||||||
|
readonly permessageDeflate?: boolean;
|
||||||
|
readonly inflateBytes?: VSBuffer;
|
||||||
|
readonly recordInflateBytes?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Protocol extends PersistentProtocol {
|
export class Protocol extends PersistentProtocol {
|
||||||
|
@ -17,7 +20,12 @@ export class Protocol extends PersistentProtocol {
|
||||||
super(
|
super(
|
||||||
options.skipWebSocketFrames
|
options.skipWebSocketFrames
|
||||||
? new NodeSocket(socket)
|
? new NodeSocket(socket)
|
||||||
: new WebSocketNodeSocket(new NodeSocket(socket), false, null, false),
|
: new WebSocketNodeSocket(
|
||||||
|
new NodeSocket(socket),
|
||||||
|
options.permessageDeflate || false,
|
||||||
|
options.inflateBytes || null,
|
||||||
|
options.recordInflateBytes || false,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ export class Vscode {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async handleWebSocket(socket: net.Socket, query: Query): Promise<true> {
|
public async handleWebSocket(socket: net.Socket, query: Query, _permessageDeflate: boolean): Promise<true> {
|
||||||
if (!query.reconnectionToken) {
|
if (!query.reconnectionToken) {
|
||||||
throw new Error('Reconnection token is missing from query parameters');
|
throw new Error('Reconnection token is missing from query parameters');
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ export class Vscode {
|
||||||
reconnectionToken: <string>query.reconnectionToken,
|
reconnectionToken: <string>query.reconnectionToken,
|
||||||
reconnection: query.reconnection === 'true',
|
reconnection: query.reconnection === 'true',
|
||||||
skipWebSocketFrames: query.skipWebSocketFrames === 'true',
|
skipWebSocketFrames: query.skipWebSocketFrames === 'true',
|
||||||
|
// TODO: permessageDeflate,
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await this.connect(await protocol.handshake(), protocol);
|
await this.connect(await protocol.handshake(), protocol);
|
||||||
|
|
|
@ -207,5 +207,8 @@ wsRouter.ws("/", ensureAuthenticated, async (req) => {
|
||||||
`Sec-WebSocket-Accept: ${reply}`,
|
`Sec-WebSocket-Accept: ${reply}`,
|
||||||
].join("\r\n") + "\r\n\r\n",
|
].join("\r\n") + "\r\n\r\n",
|
||||||
)
|
)
|
||||||
await vscode.sendWebsocket(req.ws, req.query)
|
// TODO: Parse this header properly. Currently unused so haven't bothered.
|
||||||
|
const extensions = req.headers["sec-websocket-extensions"]
|
||||||
|
const permessageDeflate = extensions ? extensions.includes("permessage-deflate") : false
|
||||||
|
await vscode.sendWebsocket(req.ws, req.query, permessageDeflate)
|
||||||
})
|
})
|
||||||
|
|
|
@ -120,12 +120,12 @@ export class VscodeProvider {
|
||||||
/**
|
/**
|
||||||
* VS Code expects a raw socket. It will handle all the web socket frames.
|
* VS Code expects a raw socket. It will handle all the web socket frames.
|
||||||
*/
|
*/
|
||||||
public async sendWebsocket(socket: net.Socket, query: ipc.Query): Promise<void> {
|
public async sendWebsocket(socket: net.Socket, query: ipc.Query, permessageDeflate: boolean): Promise<void> {
|
||||||
const vscode = await this._vscode
|
const vscode = await this._vscode
|
||||||
// TLS sockets cannot be transferred to child processes so we need an
|
// TLS sockets cannot be transferred to child processes so we need an
|
||||||
// in-between. Non-TLS sockets will be returned as-is.
|
// in-between. Non-TLS sockets will be returned as-is.
|
||||||
const socketProxy = await this.socketProvider.createProxy(socket)
|
const socketProxy = await this.socketProvider.createProxy(socket)
|
||||||
this.send({ type: "socket", query }, vscode, socketProxy)
|
this.send({ type: "socket", query, permessageDeflate }, vscode, socketProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
private send(message: ipc.CodeServerMessage, vscode?: cp.ChildProcess, socket?: net.Socket): void {
|
private send(message: ipc.CodeServerMessage, vscode?: cp.ChildProcess, socket?: net.Socket): void {
|
||||||
|
|
Loading…
Reference in New Issue