socketServer.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. 'use strict';
  2. const net = require('net'),
  3. tls = require('tls'),
  4. fs = require('fs'),
  5. dgram = require('dgram'),
  6. EventParser = require('../entities/EventParser.js'),
  7. Message = require('js-message'),
  8. Events = require('event-pubsub');
  9. let eventParser = new EventParser();
  10. class Server extends Events{
  11. constructor(path,config,log,port){
  12. super();
  13. Object.assign(
  14. this,
  15. {
  16. config : config,
  17. path : path,
  18. port : port,
  19. udp4 : false,
  20. udp6 : false,
  21. log : log,
  22. server : false,
  23. sockets : [],
  24. emit : emit,
  25. broadcast : broadcast
  26. }
  27. );
  28. eventParser=new EventParser(this.config);
  29. this.on(
  30. 'close',
  31. serverClosed.bind(this)
  32. );
  33. }
  34. onStart(socket){
  35. this.trigger(
  36. 'start',
  37. socket
  38. );
  39. }
  40. stop(){
  41. this.server.close();
  42. }
  43. start(){
  44. if(!this.path){
  45. this.log('Socket Server Path not specified, refusing to start');
  46. return;
  47. }
  48. if(this.config.unlink){
  49. fs.unlink(
  50. this.path,
  51. startServer.bind(this)
  52. );
  53. }else{
  54. startServer.bind(this)();
  55. }
  56. }
  57. }
  58. function emit(socket, type, data){
  59. this.log('dispatching event to socket', ' : ', type, data);
  60. let message=new Message;
  61. message.type=type;
  62. message.data=data;
  63. if(this.config.rawBuffer){
  64. this.log(this.config.encoding)
  65. message=Buffer.from(type,this.config.encoding);
  66. }else{
  67. message=eventParser.format(message);
  68. }
  69. if(this.udp4 || this.udp6){
  70. if(!socket.address || !socket.port){
  71. this.log('Attempting to emit to a single UDP socket without supplying socket address or port. Redispatching event as broadcast to all connected sockets');
  72. this.broadcast(type,data);
  73. return;
  74. }
  75. this.server.write(
  76. message,
  77. socket
  78. );
  79. return;
  80. }
  81. socket.write(message);
  82. }
  83. function broadcast(type,data){
  84. this.log('broadcasting event to all known sockets listening to ', this.path,' : ', ((this.port)?this.port:''), type, data);
  85. let message=new Message;
  86. message.type=type;
  87. message.data=data;
  88. if(this.config.rawBuffer){
  89. message=Buffer.from(type,this.config.encoding);
  90. }else{
  91. message=eventParser.format(message);
  92. }
  93. if(this.udp4 || this.udp6){
  94. for(let i=1, count=this.sockets.length; i<count; i++){
  95. this.server.write(message,this.sockets[i]);
  96. }
  97. }else{
  98. for(let i=0, count=this.sockets.length; i<count; i++){
  99. this.sockets[i].write(message);
  100. }
  101. }
  102. }
  103. function serverClosed(){
  104. for(let i=0, count=this.sockets.length; i<count; i++){
  105. let socket=this.sockets[i];
  106. let destroyedSocketId=false;
  107. if(socket){
  108. if(socket.readable){
  109. continue;
  110. }
  111. }
  112. if(socket.id){
  113. destroyedSocketId=socket.id;
  114. }
  115. this.log('socket disconnected',destroyedSocketId.toString());
  116. if(socket && socket.destroy){
  117. socket.destroy();
  118. }
  119. this.sockets.splice(i,1);
  120. this.publish('socket.disconnected', socket, destroyedSocketId);
  121. return;
  122. }
  123. }
  124. function gotData(socket,data,UDPSocket){
  125. let sock=((this.udp4 || this.udp6)? UDPSocket : socket);
  126. if(this.config.rawBuffer){
  127. data=Buffer.from(data,this.config.encoding);
  128. this.publish(
  129. 'data',
  130. data,
  131. sock
  132. );
  133. return;
  134. }
  135. if(!sock.ipcBuffer){
  136. sock.ipcBuffer='';
  137. }
  138. data=(sock.ipcBuffer+=data);
  139. if(data.slice(-1)!=eventParser.delimiter || data.indexOf(eventParser.delimiter) == -1){
  140. this.log('Messages are large, You may want to consider smaller messages.');
  141. return;
  142. }
  143. sock.ipcBuffer='';
  144. data=eventParser.parse(data);
  145. while(data.length>0){
  146. let message=new Message;
  147. message.load(data.shift());
  148. // Only set the sock id if it is specified.
  149. if (message.data && message.data.id){
  150. sock.id=message.data.id;
  151. }
  152. this.log('received event of : ',message.type,message.data);
  153. this.publish(
  154. message.type,
  155. message.data,
  156. sock
  157. );
  158. }
  159. }
  160. function socketClosed(socket){
  161. this.publish(
  162. 'close',
  163. socket
  164. );
  165. }
  166. function serverCreated(socket) {
  167. this.sockets.push(socket);
  168. if(socket.setEncoding){
  169. socket.setEncoding(this.config.encoding);
  170. }
  171. this.log('## socket connection to server detected ##');
  172. socket.on(
  173. 'close',
  174. socketClosed.bind(this)
  175. );
  176. socket.on(
  177. 'error',
  178. function(err){
  179. this.log('server socket error',err);
  180. this.publish('error',err);
  181. }.bind(this)
  182. );
  183. socket.on(
  184. 'data',
  185. gotData.bind(this,socket)
  186. );
  187. socket.on(
  188. 'message',
  189. function(msg,rinfo) {
  190. if (!rinfo){
  191. return;
  192. }
  193. this.log('Received UDP message from ', rinfo.address, rinfo.port);
  194. let data;
  195. if(this.config.rawSocket){
  196. data=Buffer.from(msg,this.config.encoding);
  197. }else{
  198. data=msg.toString();
  199. }
  200. socket.emit('data',data,rinfo);
  201. }.bind(this)
  202. );
  203. this.publish(
  204. 'connect',
  205. socket
  206. );
  207. if(this.config.rawBuffer){
  208. return;
  209. }
  210. }
  211. function startServer() {
  212. this.log(
  213. 'starting server on ',this.path,
  214. ((this.port)?`:${this.port}`:'')
  215. );
  216. if(!this.udp4 && !this.udp6){
  217. this.log('starting TLS server',this.config.tls);
  218. if(!this.config.tls){
  219. this.server=net.createServer(
  220. serverCreated.bind(this)
  221. );
  222. }else{
  223. startTLSServer.bind(this)();
  224. }
  225. }else{
  226. this.server=dgram.createSocket(
  227. ((this.udp4)? 'udp4':'udp6')
  228. );
  229. this.server.write=UDPWrite.bind(this);
  230. this.server.on(
  231. 'listening',
  232. function UDPServerStarted() {
  233. serverCreated.bind(this)(this.server);
  234. }.bind(this)
  235. );
  236. }
  237. this.server.on(
  238. 'error',
  239. function(err){
  240. this.log('server error',err);
  241. this.publish(
  242. 'error',
  243. err
  244. );
  245. }.bind(this)
  246. );
  247. this.server.maxConnections=this.config.maxConnections;
  248. if(!this.port){
  249. this.log('starting server as', 'Unix || Windows Socket');
  250. if (process.platform ==='win32'){
  251. this.path = this.path.replace(/^\//, '');
  252. this.path = this.path.replace(/\//g, '-');
  253. this.path= `\\\\.\\pipe\\${this.path}`;
  254. }
  255. this.server.listen({
  256. path: this.path,
  257. readableAll: this.config.readableAll,
  258. writableAll: this.config.writableAll
  259. }, this.onStart.bind(this));
  260. return;
  261. }
  262. if(!this.udp4 && !this.udp6){
  263. this.log('starting server as', (this.config.tls?'TLS':'TCP'));
  264. this.server.listen(
  265. this.port,
  266. this.path,
  267. this.onStart.bind(this)
  268. );
  269. return;
  270. }
  271. this.log('starting server as',((this.udp4)? 'udp4':'udp6'));
  272. this.server.bind(
  273. this.port,
  274. this.path
  275. );
  276. this.onStart(
  277. {
  278. address : this.path,
  279. port : this.port
  280. }
  281. );
  282. }
  283. function startTLSServer(){
  284. this.log('starting TLS server',this.config.tls);
  285. if(this.config.tls.private){
  286. this.config.tls.key=fs.readFileSync(this.config.tls.private);
  287. }else{
  288. this.config.tls.key=fs.readFileSync(`${__dirname}/../local-node-ipc-certs/private/server.key`);
  289. }
  290. if(this.config.tls.public){
  291. this.config.tls.cert=fs.readFileSync(this.config.tls.public);
  292. }else{
  293. this.config.tls.cert=fs.readFileSync(`${__dirname}/../local-node-ipc-certs/server.pub`);
  294. }
  295. if(this.config.tls.dhparam){
  296. this.config.tls.dhparam=fs.readFileSync(this.config.tls.dhparam);
  297. }
  298. if(this.config.tls.trustedConnections){
  299. if(typeof this.config.tls.trustedConnections === 'string'){
  300. this.config.tls.trustedConnections=[this.config.tls.trustedConnections];
  301. }
  302. this.config.tls.ca=[];
  303. for(let i=0; i<this.config.tls.trustedConnections.length; i++){
  304. this.config.tls.ca.push(
  305. fs.readFileSync(this.config.tls.trustedConnections[i])
  306. );
  307. }
  308. }
  309. this.server=tls.createServer(
  310. this.config.tls,
  311. serverCreated.bind(this)
  312. );
  313. }
  314. function UDPWrite(message,socket){
  315. let data=Buffer.from(message, this.config.encoding);
  316. this.server.send(
  317. data,
  318. 0,
  319. data.length,
  320. socket.port,
  321. socket.address,
  322. function(err, bytes) {
  323. if(err){
  324. this.log('error writing data to socket',err);
  325. this.publish(
  326. 'error',
  327. function(err){
  328. this.publish('error',err);
  329. }
  330. );
  331. }
  332. }
  333. );
  334. }
  335. module.exports=Server;