forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsocketServer.ts
More file actions
118 lines (112 loc) · 4.12 KB
/
socketServer.ts
File metadata and controls
118 lines (112 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
'use strict';
import * as net from 'net';
import * as fs from 'fs';
import * as os from 'os';
import { Disposable } from 'vscode'
import { createDeferred, Deferred } from '../../common/helpers';
import { EventEmitter } from 'events';
const MaxConnections = 100;
function getIPType() {
const networkInterfaces = os.networkInterfaces();
let IPType = '';
if (networkInterfaces && Array.isArray(networkInterfaces) && (networkInterfaces as any).length > 0) {
// getting the family of first network interface available
IPType = networkInterfaces[Object.keys(networkInterfaces)[0]][0].family;
}
return IPType;
}
export class Server extends EventEmitter implements Disposable {
private server: net.Server;
private startedDef: Deferred<number>;
private path: string;
private sockets: net.Socket[] = [];
private ipcBuffer: string = '';
constructor() {
super();
this.path = (getIPType() === 'IPv6') ? '::1' : '127.0.0.1';
}
public get clientsConnected(): boolean {
return this.sockets.length > 0;
}
public dispose() {
this.stop();
}
public stop() {
if (this.server) {
this.server.close();
this.server = null;
}
}
public start(): Promise<number> {
this.startedDef = createDeferred<number>()
fs.unlink(this.path, () => {
this.server = net.createServer(this.connectionListener.bind(this));
this.server.maxConnections = MaxConnections;
this.server.on('error', (err) => {
if (this.startedDef) {
this.startedDef.reject(err);
this.startedDef = null;
}
this.emit('error', err);
});
this.log('starting server as', 'TCP');
this.server.listen(0, this.path, (socket: net.Socket) => {
this.startedDef.resolve(this.server.address().port);
this.startedDef = null;
this.emit('start', socket);
});
});
return this.startedDef.promise;
}
private connectionListener(socket: net.Socket) {
this.sockets.push(socket);
socket.setEncoding('utf8');
this.log('## socket connection to server detected ##');
socket.on('close', this.onCloseSocket.bind(this));
socket.on('error', (err) => {
this.log('server socket error', err);
this.emit('error', err);
});
socket.on('data', (data) => {
let sock = socket;
// Assume we have just one client socket connection
let dataStr = this.ipcBuffer += data;
while (true) {
const startIndex = dataStr.indexOf('{');
if (startIndex === -1) {
return;
}
const lengthOfMessage = parseInt(dataStr.slice(dataStr.indexOf(':') + 1, dataStr.indexOf('{')).trim());
if (dataStr.length < startIndex + lengthOfMessage) {
return;
}
const message = JSON.parse(dataStr.substring(startIndex, lengthOfMessage + startIndex));
dataStr = this.ipcBuffer = dataStr.substring(startIndex + lengthOfMessage);
this.emit(message.event, message.body, sock);
}
});
this.emit('connect', socket);
}
private log(message, ...data) {
this.emit('log', message, ...data);
}
private onCloseSocket() {
for (let i = 0, count = this.sockets.length; i < count; i++) {
let socket = this.sockets[i];
let destroyedSocketId = false;
if (socket && socket.readable) {
continue;
}
if ((socket as any).id) {
destroyedSocketId = (socket as any).id;
}
this.log('socket disconnected', destroyedSocketId.toString());
if (socket && socket.destroy) {
socket.destroy();
}
this.sockets.splice(i, 1);
this.emit('socket.disconnected', socket, destroyedSocketId);
return;
}
}
}