-
Notifications
You must be signed in to change notification settings - Fork 0
/
socket_server.js
204 lines (177 loc) · 4.96 KB
/
socket_server.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
var config = {
listen_address: null,
http_port: 1338,
http_server: '127.0.0.1',
target_server: '127.0.0.1',
// proxy server settings
use_proxy: false,
proxy_server: '127.0.0.1',
proxy_port: 8080,
// service url to remote port mapping
services: {
'/PageCounter': 2055
},
// set services2 to map services to different ports on http_server
// set services2 as null to use above services
services2: {
'/PageCounter': 2056,
},
// printers url to printer ports mapping
printers: {
// "127.0.0.1_9100" : 9001
}
};
var configConfirmed = false;
// ---- config ends
var net = require('net');
var http = require('http');
var log = require('./log');
function fullURL(path) {
return "http://" + config.http_server + ":" + config.http_port + path;
}
function httpOptions(path) {
if (config.use_proxy) {
return {
host: config.proxy_server,
port: config.proxy_port,
path: 'http://' + config.http_server + ":" + config.http_port + path,
agent: false,
headers: {
'Connection': 'keep-alive',
'Host': config.http_server
},
method: 'POST'
};
} else {
return {
host: config.http_server,
port: config.http_port,
path: path,
agent: false,
headers: { 'Connection': 'keep-alive' },
method: 'POST'
};
}
}
function createServer(request_path) {
var server = net.createServer(function(socket) {
var http_request = null;
socket.on('connect', function() {
http_request = http.request(httpOptions(request_path), function(response) {
response.pipe(socket); // this will close socket on response ends
});
socket.pipe(http_request);
// close socket on http error
http_request.on('error', function() {
log.error("request to " + fullURL(request_path) + " error.");
socket.end();
});
});
});
return server;
}
function connectPrinterToHttpServer(address, port, socket)
{
var request_path = "/printer/" + address + "_" + port;
log.info("Connecting printer " + address + ":" + port + " to " + fullURL(request_path));
var http_request = http.request(httpOptions(request_path), function(response) {
response.pipe(socket);
response.on('end', function() {
log.info("Printer http tunnel response ends, reconnecting.");
connectPrinter(address, port);
});
});
http_request.on('error', function(e) {
log.error("Error occurs during connection with " + fullURL(request_path) + ", will retry in 1s. Error is " + e);
configConfirmed = false;
setTimeout(function() {
connectPrinterToHttpServer(address, port, socket);
}, 1000);
});
http_request.write("ping");
setInterval(function() {
http_request.write("ping");
}, 1000);
}
function connectPrinter(address, port) {
var socket_client = net.connect(port, address, function() {
log.info("Connected to printer " + address + ":" + port);
connectPrinterToHttpServer(address, port, socket_client);
});
socket_client.on('error', function(e) {
log.info("Connection to printer " + address + ":" + port + " error, reconnect: " + e);
setTimeout(function() {
connectPrinter(address, port);
}, 1000);
});
}
var serverStarted = false;
var servers = [];
function startServer() {
if (serverStarted) {
return;
}
serverStarted = true;
if (config.services) {
for(var request_path in config.services) {
var port = config.services[request_path];
var server = createServer(request_path);
server.listen(port, config.listen_address);
log.info('Server running at ' + config.listen_address + ':' + port + " for " + fullURL(request_path));
servers.push(server);
}
}
if (config.printers) {
for (var address_port in config.printers) {
var ap = address_port.split('_');
var address = ap[0];
var pport = ap[1];
connectPrinter(address, pport);
}
}
}
function _sendConfig(configCallback) {
if (configConfirmed) {
return;
}
var request_path = "/config";
var http_request = http.request(httpOptions(request_path), function(response) {
response.on('data', function(data) {
if (data == 'received') {
configConfirmed = true;
if (configCallback) {
configCallback();
}
}
});
});
http_request.end(JSON.stringify(config));
http_request.on('error', function(e) {
log.error("Error occurs _sending config, will retry in 1s. Error is " + e);
});
}
var configInterval;
function sendConfig(configCallback) {
_sendConfig(configCallback);
configInterval = setInterval(function() {
_sendConfig(configCallback);
}, 1000);
}
function start(configCallback) {
startServer();
sendConfig(configCallback);
}
function stop() {
clearInterval(configInterval);
for (var index in servers) {
var server = servers[index];
server.close();
}
}
exports.start = start;
exports.stop = stop;
exports.config = config;
// run alone
if (!module.parent) {
start();
}