microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
8a9925ee8b659b3f9dba8a521555c8ee58fd8f31

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/extensionServer.ts

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