-
Notifications
You must be signed in to change notification settings - Fork 0
/
jsonrpc.js
114 lines (106 loc) · 3.1 KB
/
jsonrpc.js
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
`use strict`;
const net = require("net");
class Client {
/**
* Constructor
* @param options
*/
constructor(options) {
this.opts = options || {};
this.socket = new net.Socket();
// id in rpc
this.counter = 1;
this.pool = new Map();
this.timer = null;
this.socket.setEncoding("utf8");
this.socket.setTimeout(3000);
}
/**
* Connect
* @return {Promise<any>}
*/
connect() {
return new Promise(((resolve, reject) => {
this.socket.on('timeout', () => {
const error = new Error('Socket timeout');
console.error(error);
this.socket.end();
reject(error);
});
let incomingData = '';
this.socket.on("data", data => {
incomingData += data.toString('utf8');
const chunks = incomingData.split('\n');
incomingData = chunks[chunks.length - 1];
for (let i = 0; i < chunks.length - 1; i++) {
try {
let obj = JSON.parse(chunks[i]);
this.data(obj);
} catch (err) {
console.error(err);
}
}
});
this.socket.on("close", () => {
if(this.timer) clearTimeout(this.timer);
this.close();
});
this.socket.on("error", error => {
if(this.timer) clearTimeout(this.timer);
console.error(error);
if(!this.socket.connecting) reject(error);
});
this.socket.on("ready", () => {
resolve('ok');
});
// connect
this.socket.connect({
host: this.opts.host || 'localhost',
port: this.opts.port || 3333
});
}));
}
/**
* Call method RPC
* @param method
* @param params
*/
call(method, params) {
return new Promise((resolve, reject) => {
let request = {
id: this.counter++,
params,
method
};
this.socket.write(JSON.stringify(request)+"\n", (error) => {
if(error) reject(error);
this.pool.set(request.id, (jsonData) => {
this.pool.delete(request.id);
resolve(jsonData);
});
});
this.timer = setTimeout(() => {
const error = new Error("Timeout request");
console.error(error);
reject(error);
}, this.opts.timeout || 60000);
});
}
/**
* Received data from socket
* @param jsonData
*/
data(jsonData) {
if(jsonData.id && this.pool.has(jsonData.id))
this.pool.get(jsonData.id)(jsonData);
}
/**
* Close socket
*/
close() {
this.pool = new Map();
this.socket.end();
this.socket.destroy();
}
}
module.exports = Client;