1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const net = require("net");
|
4 | const rpc_1 = require("./rpc");
|
5 | const debug = require("debug")("rpc");
|
6 | function connect(port = 63342, domains = null) {
|
7 | const transport = new SocketTransport();
|
8 | const server = new rpc_1.JsonRpc(transport, domains);
|
9 | transport.connect(port);
|
10 | return server;
|
11 | }
|
12 | exports.connect = connect;
|
13 | class SocketTransport {
|
14 | constructor(socket = new net.Socket()) {
|
15 | this.socket = socket;
|
16 | }
|
17 | connect(port = 63342) {
|
18 | this.socket.connect(port, null, () => {
|
19 | debug("Connected to %s", port);
|
20 | const opened = this.opened;
|
21 | if (opened != null) {
|
22 | opened();
|
23 | }
|
24 | });
|
25 | this.socket.on("error", (e) => {
|
26 | console.error(e);
|
27 | });
|
28 | const messageReceived = this.messageReceived;
|
29 | if (messageReceived == null) {
|
30 | console.warn("messageReceived is not specified, input will be ignored");
|
31 | }
|
32 | else {
|
33 | const messageDecoder = new MessageDecoder(messageReceived);
|
34 | this.socket.on("data", messageDecoder.messageReceived.bind(messageDecoder));
|
35 | }
|
36 | this.socket.write(new Buffer([67, 72, 105, -107, 126, -21, -81, -72, 64, 54, -87, -88, 0, -46, -48, 34, -7, -67]));
|
37 | }
|
38 | send(id, domain, command, params = null) {
|
39 | const encodedParams = params == null || params.length === 0 ? null : JSON.stringify(params);
|
40 | const header = '[' + (id == -1 ? '' : (id + ', ')) + '"' + domain + '", "' + command + '"';
|
41 | const headerBuffer = new Buffer(4);
|
42 | headerBuffer.writeUInt32BE(header.length + (encodedParams == null ? 0 : Buffer.byteLength(encodedParams)) + 1, 0);
|
43 | this.socket.write(headerBuffer);
|
44 | debug("out: %s%s]", header, encodedParams || "");
|
45 | this.socket.write(header);
|
46 | if (encodedParams != null) {
|
47 | this.socket.write(encodedParams);
|
48 | }
|
49 | this.socket.write(']');
|
50 | }
|
51 | sendResult(id, result) {
|
52 | this.sendResultOrError(id, result, false);
|
53 | }
|
54 | sendError(id, error) {
|
55 | this.sendResultOrError(id, error, true);
|
56 | }
|
57 | sendResultOrError(id, result, isError) {
|
58 | var encodedResult = JSON.stringify(result);
|
59 | var header = id + ', "' + (isError ? 'e' : 'r') + '"';
|
60 | const headerBuffer = new Buffer(4);
|
61 | headerBuffer.writeUInt32BE(Buffer.byteLength(encodedResult) + header.length, 0);
|
62 | this.socket.write(headerBuffer);
|
63 | this.socket.write(encodedResult);
|
64 | }
|
65 | }
|
66 | exports.SocketTransport = SocketTransport;
|
67 | class MessageDecoder {
|
68 | constructor(messageProcessor) {
|
69 | this.messageProcessor = messageProcessor;
|
70 | this.state = 0;
|
71 | this.contentLength = 0;
|
72 | this.buffers = [];
|
73 | this.readableByteCount = 0;
|
74 | this.messageBufferOffset = 0;
|
75 | }
|
76 | concatBuffer(buffer) {
|
77 | if (this.buffers.length === 0) {
|
78 | return buffer;
|
79 | }
|
80 | this.buffers.push(buffer);
|
81 | let totalBuffer = Buffer.concat(this.buffers, this.readableByteCount);
|
82 | this.buffers.length = 0;
|
83 | return totalBuffer;
|
84 | }
|
85 | messageReceived(buffer) {
|
86 | let offset = 0;
|
87 | this.readableByteCount += buffer.length;
|
88 | while (true) {
|
89 | switch (this.state) {
|
90 | case 0: {
|
91 | if (this.readableByteCount < 4) {
|
92 | if (offset != 0) {
|
93 | buffer = buffer.slice(offset);
|
94 | }
|
95 | this.buffers.push(buffer);
|
96 | return;
|
97 | }
|
98 | buffer = this.concatBuffer(buffer);
|
99 | this.state = 1;
|
100 | this.contentLength = buffer.readUInt32BE(offset);
|
101 | offset += 4;
|
102 | if ((buffer.length - offset) < this.contentLength) {
|
103 | this.messageBuffer = new Buffer(this.contentLength);
|
104 | buffer.copy(this.messageBuffer, 0, offset);
|
105 | this.messageBufferOffset = 0;
|
106 | this.readableByteCount = 0;
|
107 | return;
|
108 | }
|
109 | this.readableByteCount = buffer.length - offset;
|
110 | }
|
111 | case 1: {
|
112 | let rawMessage;
|
113 | if (this.messageBuffer == null) {
|
114 | rawMessage = buffer.toString("utf8", offset, offset + this.contentLength);
|
115 | offset += this.contentLength;
|
116 | this.readableByteCount = buffer.length - offset;
|
117 | }
|
118 | else {
|
119 | const requiredByteCount = this.messageBuffer.length - this.messageBufferOffset;
|
120 | if (requiredByteCount > this.readableByteCount) {
|
121 | buffer.copy(this.messageBuffer, this.messageBufferOffset, offset);
|
122 | this.messageBufferOffset += this.readableByteCount;
|
123 | this.readableByteCount = 0;
|
124 | return;
|
125 | }
|
126 | else {
|
127 | const newOffset = offset + requiredByteCount;
|
128 | buffer.copy(this.messageBuffer, this.messageBufferOffset, offset, newOffset);
|
129 | offset = newOffset;
|
130 | this.readableByteCount = buffer.length - offset;
|
131 | rawMessage = this.messageBuffer.toString("utf8");
|
132 | }
|
133 | }
|
134 | debug("in: %s", rawMessage);
|
135 | try {
|
136 | this.state = 0;
|
137 | this.contentLength = 0;
|
138 | this.messageProcessor(JSON.parse(rawMessage));
|
139 | }
|
140 | catch (e) {
|
141 | console.error("Error: %s,\nInput: %s", e, rawMessage);
|
142 | }
|
143 | }
|
144 | }
|
145 | }
|
146 | }
|
147 | }
|
148 |
|
\ | No newline at end of file |