microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
445b113fa38f291ca910604a6a87bab6cb5f95e9

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/extensionServer.ts

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