socketServer.js 9.4 KB

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