microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
bf6ca50469e7197ca79e913dfab8ef6372097a15

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/extensionServer.ts

145lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as em from "../common/extensionMessaging";
5import {FileSystem} from "../common/node/fileSystem";
6import {Packager} from "../common/packager";
7import {Log} from "../common/log/log";
8import {LogLevel} from "../common/log/logHelper";
9import * as Q from "q";
10import * as net from "net";
11import * as vscode from "vscode";
12
13
14export class ExtensionServer implements vscode.Disposable {
15 private serverInstance: net.Server = null;
16 private messageHandlerDictionary: { [id: number]: ((...argArray: any[]) => Q.Promise<any>) } = {};
17 private reactNativePackager: Packager;
18
19 public constructor(reactNativePackager: Packager) {
20 this.reactNativePackager = reactNativePackager;
21
22 /* register handlers for all messages */
23 this.messageHandlerDictionary[em.ExtensionMessage.START_PACKAGER] = this.startPackager;
24 this.messageHandlerDictionary[em.ExtensionMessage.STOP_PACKAGER] = this.stopPackager;
25 this.messageHandlerDictionary[em.ExtensionMessage.PREWARM_BUNDLE_CACHE] = this.prewarmBundleCache;
26 }
27
28 /**
29 * Starts the server.
30 */
31 public setup(): Q.Promise<void> {
32
33 let deferred = Q.defer<void>();
34
35 let launchCallback = (error: any) => {
36 Log.logInternalMessage(LogLevel.Info, "Extension messaging server started.");
37 if (error) {
38 deferred.reject(error);
39 } else {
40 deferred.resolve(null);
41 }
42 };
43
44 this.serverInstance = net.createServer(this.handleSocket.bind(this));
45 this.serverInstance.on("error", this.recoverServer.bind(this));
46 this.serverInstance.listen(em.getPipePath(), launchCallback);
47
48 return deferred.promise;
49 }
50
51 /**
52 * Stops the server.
53 */
54 public dispose(): void {
55 if (this.serverInstance) {
56 this.serverInstance.close();
57 this.serverInstance = null;
58 }
59 }
60
61 /**
62 * Message handler for START_PACKAGER.
63 */
64 private startPackager(): Q.Promise<any> {
65 return this.reactNativePackager.start();
66 }
67
68 /**
69 * Message handler for STOP_PACKAGER.
70 */
71 private stopPackager(): Q.Promise<any> {
72 return this.reactNativePackager.stop();
73 }
74
75 /**
76 * Message handler for PREWARM_BUNDLE_CACHE.
77 */
78 private prewarmBundleCache(platform: string): Q.Promise<any> {
79 return this.reactNativePackager.prewarmBundleCache(platform);
80 }
81
82 /**
83 * Extension message handler.
84 */
85 private handleExtensionMessage(messageWithArgs: em.MessageWithArguments): Q.Promise<any> {
86 let handler = this.messageHandlerDictionary[messageWithArgs.message];
87 if (handler) {
88 Log.logInternalMessage(LogLevel.Info, "Handling message: " + em.ExtensionMessage[messageWithArgs.message]);
89 return handler.apply(this, messageWithArgs.args);
90 } else {
91 return Q.reject("Invalid message: " + messageWithArgs.message);
92 }
93 }
94
95 /**
96 * Handles connections to the server.
97 */
98 private handleSocket(socket: net.Socket): void {
99 let handleError = (e: any) => {
100 Log.logError("An error ocurred. ", e);
101 socket.end(em.ErrorMarker);
102 };
103
104 let dataCallback = (data: any) => {
105 try {
106 let messageWithArgs: em.MessageWithArguments = JSON.parse(data);
107 this.handleExtensionMessage(messageWithArgs)
108 .then(result => {
109 socket.end(JSON.stringify(result));
110 })
111 .catch((e) => { handleError(e); })
112 .done();
113 } catch (e) {
114 handleError(e);
115 }
116 };
117
118 socket.on("data", dataCallback);
119 };
120
121 /**
122 * Recovers the server in case the named socket we use already exists, but no other instance of VSCode is active.
123 */
124 private recoverServer(error: any): void {
125 let errorHandler = (e: any) => {
126 /* The named socket is not used. */
127 if (e.code === "ECONNREFUSED") {
128 new FileSystem().removePathRecursivelyAsync(em.getPipePath())
129 .then(() => {
130 this.serverInstance.listen(em.getPipePath());
131 })
132 .done();
133 }
134 };
135
136 /* The named socket already exists. */
137 if (error.code === "EADDRINUSE") {
138 let clientSocket = new net.Socket();
139 clientSocket.on("error", errorHandler);
140 clientSocket.connect(em.getPipePath(), function() {
141 clientSocket.end();
142 });
143 }
144 }
145}
146