1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | const
|
15 | appc = require('node-appc'),
|
16 | EventEmitter = require('events').EventEmitter,
|
17 | net = require('net'),
|
18 | util = require('util'),
|
19 | uuid = require('uuid'),
|
20 | __ = appc.i18n(__dirname).__;
|
21 |
|
22 | module.exports = LogRelay;
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | function LogRelay(opts) {
|
38 | opts || (opts = {});
|
39 |
|
40 |
|
41 | this.serverToken = opts.serverToken || uuid.v4();
|
42 |
|
43 | this.includeInternalIPAddresses = opts.includeInternalIPAddresses !== void 0 ? opts.includeInternalIPAddresses : true;
|
44 |
|
45 | this.ipAddressList = [];
|
46 | this.tcpPort = opts.tcpPort || 8666;
|
47 | this.tcpServer = null;
|
48 | }
|
49 |
|
50 | util.inherits(LogRelay, EventEmitter);
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | LogRelay.prototype.start = function start(options, callback) {
|
65 | if (typeof options === 'function') {
|
66 | callback = options;
|
67 | options = {};
|
68 | } else if (!options) {
|
69 | options = {};
|
70 | }
|
71 | typeof callback === 'function' || (callback = function () {});
|
72 |
|
73 | var self = this;
|
74 |
|
75 | appc.net.interfaces(function (ifaces) {
|
76 | Object.keys(ifaces).forEach(function (name) {
|
77 | ifaces[name].ipAddresses.forEach(function (ip) {
|
78 | if (/IPv4/i.test(ip.family) && (!ip.internal || self.includeInternalIPAddresses === void 0 || self.includeInternalIPAddresses)) {
|
79 | self.ipAddressList.push(ip.address);
|
80 | }
|
81 | });
|
82 | });
|
83 |
|
84 |
|
85 |
|
86 | (function startTCPServer() {
|
87 |
|
88 | if (self.tcpServer) {
|
89 | try {
|
90 | self.tcpServer.close();
|
91 | } catch (e) {}
|
92 | self.tcpServer = null;
|
93 | }
|
94 |
|
95 | var tcpServer = self.tcpServer = net.createServer(handleLogConnection);
|
96 |
|
97 | tcpServer.on('error', function (e) {
|
98 | if (e.code == 'EADDRINUSE') {
|
99 | self.emit('log-debug', __('Log relay failed to bind to port %s, trying port %s', self.tcpPort, self.tcpPort + 1));
|
100 | self.tcpPort++;
|
101 | startTCPServer();
|
102 | } else {
|
103 | self.stop();
|
104 | var ex = new Error(__('TCP server error: %s', e.toString()));
|
105 | self.emit('error', ex);
|
106 | callback(ex);
|
107 | }
|
108 | });
|
109 |
|
110 | tcpServer.listen(self.tcpPort, function () {
|
111 | self.emit('log-debug', __('Log relay listening on port %s on %s', self.tcpPort, self.ipAddressList.join(', ')));
|
112 | self.emit('started', this);
|
113 | callback(null, this);
|
114 | });
|
115 | }());
|
116 |
|
117 | function emitLines(lines) {
|
118 | var len = lines.length;
|
119 |
|
120 |
|
121 |
|
122 | if (len > 0 && lines[len - 1] === '') {
|
123 | len--;
|
124 | }
|
125 |
|
126 | for (var i = 0; i < len; i++) {
|
127 | self.emit('message', lines[i]);
|
128 | }
|
129 | }
|
130 |
|
131 | function handleLogConnection(conn) {
|
132 | self.emit('connection', conn);
|
133 |
|
134 | var initialized = false,
|
135 | buffer = '',
|
136 | timer;
|
137 |
|
138 | conn.on('data', function (data) {
|
139 | clearTimeout(timer);
|
140 |
|
141 | var lines = (buffer + data.toString()).split('\n');
|
142 |
|
143 | if (!initialized) {
|
144 | if (lines[0] !== self.serverToken) {
|
145 |
|
146 | conn.destroy();
|
147 | return;
|
148 | }
|
149 |
|
150 | lines.splice(0, 1);
|
151 | initialized = true;
|
152 | }
|
153 |
|
154 |
|
155 | buffer = lines.pop();
|
156 |
|
157 |
|
158 | emitLines(lines);
|
159 |
|
160 |
|
161 | timer = setTimeout(function () {
|
162 | emitLines(buffer.split('\n'));
|
163 | buffer = '';
|
164 | }, 2000);
|
165 | });
|
166 |
|
167 | conn.on('close', function () {
|
168 |
|
169 | emitLines(buffer.split('\n'));
|
170 | buffer = '';
|
171 |
|
172 | self.emit('disconnect', conn);
|
173 | });
|
174 |
|
175 | conn.on('error', function () {});
|
176 | };
|
177 | });
|
178 | };
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 | LogRelay.prototype.stop = function stop() {
|
186 | if (this.tcpServer) {
|
187 | this.tcpServer.close();
|
188 | this.tcpServer = null;
|
189 | }
|
190 |
|
191 | this.emit('stopped');
|
192 | };
|