microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.1.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/extensionServer.ts

185lines · 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 net from "net";
5import * as Q from "q";
6import * as vscode from "vscode";
7
8import * as em from "../common/extensionMessaging";
9import {HostPlatform} from "../common/hostPlatform";
10import {Log} from "../common/log/log";
11import {LogLevel} from "../common/log/logHelper";
12import {Packager} from "../common/packager";
13import {PackagerStatus, PackagerStatusIndicator} from "./packagerStatusIndicator";
14import {LogCatMonitor} from "./android/logCatMonitor";
15import {FileSystem} from "../common/node/fileSystem";
16
17export class ExtensionServer implements vscode.Disposable {
18 private serverInstance: net.Server = null;
19 private messageHandlerDictionary: { [id: number]: ((...argArray: any[]) => Q.Promise<any>) } = {};
20 private reactNativePackager: Packager;
21 private reactNativePackageStatusIndicator: PackagerStatusIndicator;
22 private pipePath: string;
23 private logCatMonitor: LogCatMonitor = null;
24
25 public constructor(reactNativePackager: Packager, packagerStatusIndicator: PackagerStatusIndicator) {
26
27 this.pipePath = HostPlatform.getExtensionPipePath();
28 this.reactNativePackager = reactNativePackager;
29 this.reactNativePackageStatusIndicator = packagerStatusIndicator;
30
31 /* register handlers for all messages */
32 this.messageHandlerDictionary[em.ExtensionMessage.START_PACKAGER] = this.startPackager;
33 this.messageHandlerDictionary[em.ExtensionMessage.STOP_PACKAGER] = this.stopPackager;
34 this.messageHandlerDictionary[em.ExtensionMessage.PREWARM_BUNDLE_CACHE] = this.prewarmBundleCache;
35 this.messageHandlerDictionary[em.ExtensionMessage.START_MONITORING_LOGCAT] = this.startMonitoringLogCat;
36 this.messageHandlerDictionary[em.ExtensionMessage.STOP_MONITORING_LOGCAT] = this.stopMonitoringLogCat;
37 }
38
39 /**
40 * Starts the server.
41 */
42 public setup(): Q.Promise<void> {
43
44 let deferred = Q.defer<void>();
45
46 let launchCallback = (error: any) => {
47 Log.logInternalMessage(LogLevel.Info, "Extension messaging server started.");
48 if (error) {
49 deferred.reject(error);
50 } else {
51 deferred.resolve(null);
52 }
53 };
54
55 this.serverInstance = net.createServer(this.handleSocket.bind(this));
56 this.serverInstance.on("error", this.recoverServer.bind(this));
57 this.serverInstance.listen(this.pipePath, launchCallback);
58
59 return deferred.promise;
60 }
61
62 /**
63 * Stops the server.
64 */
65 public dispose(): void {
66 if (this.serverInstance) {
67 this.serverInstance.close();
68 this.serverInstance = null;
69 }
70
71 this.stopMonitoringLogCat();
72 }
73
74 /**
75 * Message handler for START_PACKAGER.
76 */
77 private startPackager(): Q.Promise<any> {
78 return this.reactNativePackager.start()
79 .then(() => this.reactNativePackageStatusIndicator.updatePackagerStatus(PackagerStatus.PACKAGER_STARTED));
80 }
81
82 /**
83 * Message handler for STOP_PACKAGER.
84 */
85 private stopPackager(): Q.Promise<any> {
86 return this.reactNativePackager.stop()
87 .then(() => this.reactNativePackageStatusIndicator.updatePackagerStatus(PackagerStatus.PACKAGER_STOPPED));
88 }
89
90 /**
91 * Message handler for PREWARM_BUNDLE_CACHE.
92 */
93 private prewarmBundleCache(platform: string): Q.Promise<any> {
94 return this.reactNativePackager.prewarmBundleCache(platform);
95 }
96
97 /**
98 * Message handler for START_MONITORING_LOGCAT.
99 */
100 private startMonitoringLogCat(deviceId: string, logCatArguments: string): Q.Promise<any> {
101 this.stopMonitoringLogCat(); // Stop previous logcat monitor if it's running
102
103 // this.logCatMonitor can be mutated, so we store it locally too
104 const logCatMonitor = this.logCatMonitor = new LogCatMonitor(deviceId, logCatArguments);
105 logCatMonitor.start() // The LogCat will continue running forever, so we don't wait for it
106 .catch(error =>
107 Log.logWarning("Error while monitoring LogCat", error))
108 .done();
109
110 return Q.resolve<void>(void 0);
111 }
112
113 private stopMonitoringLogCat(): Q.Promise<void> {
114 if (this.logCatMonitor) {
115 this.logCatMonitor.dispose();
116 this.logCatMonitor = null;
117 }
118
119 return Q.resolve<void>(void 0);
120 }
121
122 /**
123 * Extension message handler.
124 */
125 private handleExtensionMessage(messageWithArgs: em.MessageWithArguments): Q.Promise<any> {
126 let handler = this.messageHandlerDictionary[messageWithArgs.message];
127 if (handler) {
128 Log.logInternalMessage(LogLevel.Info, "Handling message: " + em.ExtensionMessage[messageWithArgs.message]);
129 return handler.apply(this, messageWithArgs.args);
130 } else {
131 return Q.reject("Invalid message: " + messageWithArgs.message);
132 }
133 }
134
135 /**
136 * Handles connections to the server.
137 */
138 private handleSocket(socket: net.Socket): void {
139 let handleError = (e: any) => {
140 Log.logError("An error ocurred. ", e);
141 socket.end(em.ErrorMarker);
142 };
143
144 let dataCallback = (data: any) => {
145 try {
146 let messageWithArgs: em.MessageWithArguments = JSON.parse(data);
147 this.handleExtensionMessage(messageWithArgs)
148 .then(result => {
149 socket.end(JSON.stringify(result));
150 })
151 .catch((e) => { handleError(e); })
152 .done();
153 } catch (e) {
154 handleError(e);
155 }
156 };
157
158 socket.on("data", dataCallback);
159 };
160
161 /**
162 * Recovers the server in case the named socket we use already exists, but no other instance of VSCode is active.
163 */
164 private recoverServer(error: any): void {
165 let errorHandler = (e: any) => {
166 /* The named socket is not used. */
167 if (e.code === "ECONNREFUSED") {
168 new FileSystem().removePathRecursivelyAsync(this.pipePath)
169 .then(() => {
170 this.serverInstance.listen(this.pipePath);
171 })
172 .done();
173 }
174 };
175
176 /* The named socket already exists. */
177 if (error.code === "EADDRINUSE") {
178 let clientSocket = new net.Socket();
179 clientSocket.on("error", errorHandler);
180 clientSocket.connect(this.pipePath, function() {
181 clientSocket.end();
182 });
183 }
184 }
185}