@@ -1225,10 +1225,10 @@ index 0000000000000000000000000000000000000000..4ea6d95d36aaac07dbd4d0e16ab3c1bb
1225
1225
+ }
1226
1226
diff --git a/src/vs/server/entry.ts b/src/vs/server/entry.ts
1227
1227
new file mode 100644
1228
- index 0000000000000000000000000000000000000000..ab020fbb4e4ab3748cc807765ff9c362389faafa
1228
+ index 0000000000000000000000000000000000000000..8482c48bae007ed6b39183001ae2cc6d140fcd50
1229
1229
--- /dev/null
1230
1230
+++ b/src/vs/server/entry.ts
1231
- @@ -0,0 +1,78 @@
1231
+ @@ -0,0 +1,79 @@
1232
1232
+ import { field } from '@coder/logger';
1233
1233
+ import { setUnexpectedErrorHandler } from 'vs/base/common/errors';
1234
1234
+ import { CodeServerMessage, VscodeMessage } from 'vs/server/ipc';
@@ -1273,7 +1273,8 @@ index 0000000000000000000000000000000000000000..ab020fbb4e4ab3748cc807765ff9c362
1273
1273
+ // Wait for the init message then start up VS Code. Subsequent messages will
1274
1274
+ // return new workbench options without starting a new instance.
1275
1275
+ process.on('message', async (message: CodeServerMessage, socket) => {
1276
- + logger.debug('got message from code-server', field('message', message));
1276
+ + logger.debug('got message from code-server', field('type', message.type));
1277
+ + logger.trace('code-server message content', field('message', message));
1277
1278
+ switch (message.type) {
1278
1279
+ case 'init':
1279
1280
+ try {
@@ -1821,21 +1822,20 @@ index 0000000000000000000000000000000000000000..609c4d1cb43f52f92906b901c14c790f
1821
1822
+ }
1822
1823
diff --git a/src/vs/server/node/connection.ts b/src/vs/server/node/connection.ts
1823
1824
new file mode 100644
1824
- index 0000000000000000000000000000000000000000..eec198c948d48b1539ff46510016f759f396be18
1825
+ index 0000000000000000000000000000000000000000..93062cadc627c61e0829c27a72894b81e6a0e039
1825
1826
--- /dev/null
1826
1827
+++ b/src/vs/server/node/connection.ts
1827
- @@ -0,0 +1,157 @@
1828
+ @@ -0,0 +1,171 @@
1829
+ + import { field, Logger, logger } from '@coder/logger';
1828
1830
+ import * as cp from 'child_process';
1829
1831
+ import { VSBuffer } from 'vs/base/common/buffer';
1830
1832
+ import { Emitter } from 'vs/base/common/event';
1831
1833
+ import { FileAccess } from 'vs/base/common/network';
1832
1834
+ import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
1833
1835
+ import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
1834
1836
+ import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
1835
- + import { ILogService } from 'vs/platform/log/common/log';
1836
1837
+ import { getNlsConfiguration } from 'vs/server/node/nls';
1837
1838
+ import { Protocol } from 'vs/server/node/protocol';
1838
- + import { IExtHostReadyMessage } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
1839
1839
+
1840
1840
+ export abstract class Connection {
1841
1841
+ private readonly _onClose = new Emitter<void>();
@@ -1899,13 +1899,14 @@ index 0000000000000000000000000000000000000000..eec198c948d48b1539ff46510016f759
1899
1899
+
1900
1900
+ export class ExtensionHostConnection extends Connection {
1901
1901
+ private process?: cp.ChildProcess;
1902
+ + private readonly logger: Logger;
1902
1903
+
1903
1904
+ public constructor(
1904
1905
+ locale:string, protocol: Protocol, buffer: VSBuffer, token: string,
1905
- + private readonly log: ILogService,
1906
1906
+ private readonly environment: INativeEnvironmentService,
1907
1907
+ ) {
1908
1908
+ super(protocol, token);
1909
+ + this.logger = logger.named("exthost", field("token", token));
1909
1910
+ this.protocol.dispose();
1910
1911
+ this.spawn(locale, buffer).then((p) => this.process = p);
1911
1912
+ this.protocol.getUnderlyingSocket().pause();
@@ -1928,6 +1929,7 @@ index 0000000000000000000000000000000000000000..eec198c948d48b1539ff46510016f759
1928
1929
+ private sendInitMessage(buffer: VSBuffer): void {
1929
1930
+ const socket = this.protocol.getUnderlyingSocket();
1930
1931
+ socket.pause();
1932
+ + this.logger.trace('Sending socket');
1931
1933
+ this.process!.send({ // Process must be set at this point.
1932
1934
+ type: 'VSCODE_EXTHOST_IPC_SOCKET',
1933
1935
+ initialDataChunk: (buffer.buffer as Buffer).toString('base64'),
@@ -1936,7 +1938,9 @@ index 0000000000000000000000000000000000000000..eec198c948d48b1539ff46510016f759
1936
1938
+ }
1937
1939
+
1938
1940
+ private async spawn(locale: string, buffer: VSBuffer): Promise<cp.ChildProcess> {
1941
+ + this.logger.trace('Getting NLS configuration...');
1939
1942
+ const config = await getNlsConfiguration(locale, this.environment.userDataPath);
1943
+ + this.logger.trace('Spawning extension host...');
1940
1944
+ const proc = cp.fork(
1941
1945
+ FileAccess.asFileUri('bootstrap-fork', require).fsPath,
1942
1946
+ [ '--type=extensionHost' ],
@@ -1956,30 +1960,41 @@ index 0000000000000000000000000000000000000000..eec198c948d48b1539ff46510016f759
1956
1960
+ },
1957
1961
+ );
1958
1962
+
1959
- + proc.on('error', () => this.dispose());
1960
- + proc.on('exit', () => this.dispose());
1963
+ + proc.on('error', (error) => {
1964
+ + this.logger.error('Exited unexpectedly', field('error', error));
1965
+ + this.dispose();
1966
+ + });
1967
+ + proc.on('exit', (code) => {
1968
+ + this.logger.trace('Exited', field('code', code));
1969
+ + this.dispose();
1970
+ + });
1961
1971
+ if (proc.stdout && proc.stderr) {
1962
- + proc.stdout.setEncoding('utf8').on('data', (d) => this.log .info('Extension host stdout', d));
1963
- + proc.stderr.setEncoding('utf8').on('data', (d) => this.log .error('Extension host stderr', d));
1972
+ + proc.stdout.setEncoding('utf8').on('data', (d) => this.logger .info(d));
1973
+ + proc.stderr.setEncoding('utf8').on('data', (d) => this.logger .error(d));
1964
1974
+ }
1975
+ +
1965
1976
+ proc.on('message', (event) => {
1966
- + if (event && event.type === '__$console') {
1967
- + const severity = (<any>this.log)[event.severity] ? event.severity : 'info';
1968
- + (<any>this.log)[severity]('Extension host', event.arguments);
1969
- + }
1970
- + if (event && event.type === 'VSCODE_EXTHOST_DISCONNECTED') {
1971
- + this.setOffline();
1977
+ + switch (event && event.type) {
1978
+ + case '__$console':
1979
+ + const severity = (<any>this.logger)[event.severity] || 'info';
1980
+ + (<any>this.logger)[severity]('console', field('arguments', event.arguments));
1981
+ + break;
1982
+ + case 'VSCODE_EXTHOST_DISCONNECTED':
1983
+ + this.logger.trace('Going offline');
1984
+ + this.setOffline();
1985
+ + break;
1986
+ + case 'VSCODE_EXTHOST_IPC_READY':
1987
+ + this.logger.trace('Got ready message');
1988
+ + this.sendInitMessage(buffer);
1989
+ + break;
1990
+ + default:
1991
+ + this.logger.error('Unexpected message', field("event", event));
1992
+ + break;
1972
1993
+ }
1973
1994
+ });
1974
1995
+
1975
- + const listen = (message: IExtHostReadyMessage) => {
1976
- + if (message.type === 'VSCODE_EXTHOST_IPC_READY') {
1977
- + proc.removeListener('message', listen);
1978
- + this.sendInitMessage(buffer);
1979
- + }
1980
- + };
1981
- +
1982
- + return proc.on('message', listen);
1996
+ + this.logger.trace('Waiting for handshake...');
1997
+ + return proc;
1983
1998
+ }
1984
1999
+ }
1985
2000
diff --git a/src/vs/server/node/insights.ts b/src/vs/server/node/insights.ts
@@ -2463,15 +2478,17 @@ index 0000000000000000000000000000000000000000..3d428a57d31f29c40f9c3ce45f715b44
2463
2478
+ };
2464
2479
diff --git a/src/vs/server/node/protocol.ts b/src/vs/server/node/protocol.ts
2465
2480
new file mode 100644
2466
- index 0000000000000000000000000000000000000000..3c74512192aec6220216bc8563b3127b9cfd5fbf
2481
+ index 0000000000000000000000000000000000000000..0d9310038c0ca378579652d89bc8ac84924213db
2467
2482
--- /dev/null
2468
2483
+++ b/src/vs/server/node/protocol.ts
2469
- @@ -0,0 +1,73 @@
2484
+ @@ -0,0 +1,91 @@
2485
+ + import { field } from '@coder/logger';
2470
2486
+ import * as net from 'net';
2471
2487
+ import { VSBuffer } from 'vs/base/common/buffer';
2472
2488
+ import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net';
2473
2489
+ import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
2474
2490
+ import { AuthRequest, ConnectionTypeRequest, HandshakeMessage } from 'vs/platform/remote/common/remoteAgentConnection';
2491
+ + import { logger } from 'vs/server/node/logger';
2475
2492
+
2476
2493
+ export interface SocketOptions {
2477
2494
+ readonly reconnectionToken: string;
@@ -2499,29 +2516,45 @@ index 0000000000000000000000000000000000000000..3c74512192aec6220216bc8563b3127b
2499
2516
+ * Perform a handshake to get a connection request.
2500
2517
+ */
2501
2518
+ public handshake(): Promise<ConnectionTypeRequest> {
2519
+ + logger.trace('Protocol handshake', field('token', this.options.reconnectionToken));
2502
2520
+ return new Promise((resolve, reject) => {
2521
+ + const timeout = setTimeout(() => {
2522
+ + logger.error('Handshake timed out', field('token', this.options.reconnectionToken));
2523
+ + reject(new Error("timed out"));
2524
+ + }, 10000); // Matches the client timeout.
2525
+ +
2503
2526
+ const handler = this.onControlMessage((rawMessage) => {
2504
2527
+ try {
2505
- + const message = JSON.parse(rawMessage.toString());
2528
+ + const raw = rawMessage.toString();
2529
+ + logger.trace('Protocol message', field('token', this.options.reconnectionToken), field('message', raw));
2530
+ + const message = JSON.parse(raw);
2506
2531
+ switch (message.type) {
2507
- + case 'auth': return this.authenticate(message);
2532
+ + case 'auth':
2533
+ + return this.authenticate(message);
2508
2534
+ case 'connectionType':
2509
2535
+ handler.dispose();
2536
+ + clearTimeout(timeout);
2510
2537
+ return resolve(message);
2511
- + default: throw new Error('Unrecognized message type');
2538
+ + default:
2539
+ + throw new Error('Unrecognized message type');
2512
2540
+ }
2513
2541
+ } catch (error) {
2514
2542
+ handler.dispose();
2543
+ + clearTimeout(timeout);
2515
2544
+ reject(error);
2516
2545
+ }
2517
2546
+ });
2547
+ +
2548
+ + // Kick off the handshake in case we missed the client's opening shot.
2549
+ + // TODO: Investigate why that message seems to get lost.
2550
+ + this.authenticate();
2518
2551
+ });
2519
2552
+ }
2520
2553
+
2521
2554
+ /**
2522
2555
+ * TODO: This ignores the authentication process entirely for now.
2523
2556
+ */
2524
- + private authenticate(_message : AuthRequest): void {
2557
+ + private authenticate(_? : AuthRequest): void {
2525
2558
+ this.sendMessage({ type: 'sign', data: '' });
2526
2559
+ }
2527
2560
+
@@ -2542,10 +2575,11 @@ index 0000000000000000000000000000000000000000..3c74512192aec6220216bc8563b3127b
2542
2575
+ }
2543
2576
diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts
2544
2577
new file mode 100644
2545
- index 0000000000000000000000000000000000000000..a1289865858f405f93d3d396f41c6a0aadffd5e5
2578
+ index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae095109eb1
2546
2579
--- /dev/null
2547
2580
+++ b/src/vs/server/node/server.ts
2548
- @@ -0,0 +1,286 @@
2581
+ @@ -0,0 +1,291 @@
2582
+ + import { field } from '@coder/logger';
2549
2583
+ import * as fs from 'fs';
2550
2584
+ import * as net from 'net';
2551
2585
+ import * as path from 'path';
@@ -2709,6 +2743,7 @@ index 0000000000000000000000000000000000000000..a1289865858f405f93d3d396f41c6a0a
2709
2743
+ );
2710
2744
+ }
2711
2745
+
2746
+ + logger.debug('New connection', field('token', token));
2712
2747
+ protocol.sendMessage(await ok());
2713
2748
+
2714
2749
+ let connection: Connection;
@@ -2727,12 +2762,14 @@ index 0000000000000000000000000000000000000000..a1289865858f405f93d3d396f41c6a0a
2727
2762
+ connection = new ExtensionHostConnection(
2728
2763
+ message.args ? message.args.language : 'en',
2729
2764
+ protocol, buffer, token,
2730
- + this.services.get(ILogService) as ILogService,
2731
2765
+ this.services.get(IEnvironmentService) as INativeEnvironmentService,
2732
2766
+ );
2733
2767
+ }
2734
2768
+ connections.set(token, connection);
2735
- + connection.onClose(() => connections.delete(token));
2769
+ + connection.onClose(() => {
2770
+ + logger.debug('Connection closed', field('token', token));
2771
+ + connections.delete(token);
2772
+ + });
2736
2773
+ this.disposeOldOfflineConnections(connections);
2737
2774
+ break;
2738
2775
+ case ConnectionType.Tunnel: return protocol.tunnel();
@@ -2744,6 +2781,7 @@ index 0000000000000000000000000000000000000000..a1289865858f405f93d3d396f41c6a0a
2744
2781
+ const offline = Array.from(connections.values())
2745
2782
+ .filter((connection) => typeof connection.offline !== 'undefined');
2746
2783
+ for (let i = 0, max = offline.length - this.maxExtraOfflineConnections; i < max; ++i) {
2784
+ + logger.debug('Disposing offline connection', field("token", offline[i].token));
2747
2785
+ offline[i].dispose();
2748
2786
+ }
2749
2787
+ }
0 commit comments