2014-02-27 09:04:09 +11:00
var net = require ( 'net' ) ,
2015-09-28 14:52:16 +10:00
tls = require ( 'tls' ) ,
2014-02-27 09:04:09 +11:00
fs = require ( 'fs' ) ,
dgram = require ( 'dgram' ) ,
2014-02-22 20:13:31 +11:00
eventParser = require ( '../lib/eventParser.js' ) ,
2015-09-27 20:32:14 +10:00
pubsub = require ( 'event-pubsub' ) ,
Message = require ( 'js-message' ) ;
2014-02-22 20:13:31 +11:00
function emit ( socket , type , data ) {
this . log ( 'dispatching event to socket' . debug , ' : ' , type . data , data ) ;
2015-09-27 20:32:14 +10:00
var message = new Message ;
message . type = type ;
message . data = data ;
2015-08-23 15:46:55 +10:00
if ( this . config . rawBuffer ) {
2015-09-27 20:32:14 +10:00
message = new Buffer ( type , this . encoding ) ;
2015-08-23 15:46:55 +10:00
} else {
2015-09-27 20:32:14 +10:00
message = eventParser . format ( message ) ;
2015-08-23 15:46:55 +10:00
}
2014-02-27 09:04:09 +11:00
if ( this . udp4 || this . udp6 ) {
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
if ( ! socket . address || ! socket . port ) {
this . log ( 'Attempting to emit to a single UDP socket without supplying socket address or port. Redispatching event as broadcast to all connected sockets' ) ;
this . broadcast ( type , data ) ;
return ;
}
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
this . server . write (
2015-09-27 20:32:14 +10:00
message ,
2014-02-27 09:04:09 +11:00
socket
2015-08-23 15:46:55 +10:00
) ;
2014-02-27 09:04:09 +11:00
return ;
} ;
2015-09-27 20:32:14 +10:00
socket . write ( message ) ;
2014-02-22 20:13:31 +11:00
} ;
function broadcast ( type , data ) {
2014-05-08 03:40:13 +10:00
this . log ( 'broadcasting event to all known sockets listening to ' . debug , this . path . variable , ' : ' , ( ( this . port ) ? this . port : '' ) , type , data ) ;
2015-09-27 20:32:14 +10:00
var message = new Message ;
message . type = type ;
message . data = data ;
2015-08-23 15:46:55 +10:00
if ( this . config . rawBuffer ) {
2015-09-27 20:32:14 +10:00
message = new Buffer ( type , this . encoding ) ;
2015-08-23 15:46:55 +10:00
} else {
2015-09-27 20:32:14 +10:00
message = eventParser . format ( message ) ;
2015-08-23 15:46:55 +10:00
}
2014-02-27 09:04:09 +11:00
if ( this . udp4 || this . udp6 ) {
2014-08-28 12:09:01 +10:00
for ( var i = 1 , count = this . sockets . length ; i < count ; i ++ ) {
2015-09-27 20:32:14 +10:00
this . server . write ( message , this . sockets [ i ] ) ;
2014-02-27 09:04:09 +11:00
}
} else {
for ( var i = 0 , count = this . sockets . length ; i < count ; i ++ ) {
2015-09-27 20:32:14 +10:00
this . sockets [ i ] . write ( message ) ;
2014-02-27 09:04:09 +11:00
}
2014-02-22 20:13:31 +11:00
}
} ;
2014-02-26 12:15:43 +11:00
function init ( path , config , log , port ) {
2014-02-22 20:13:31 +11:00
var server = {
config : config ,
path : path ,
2014-02-26 12:15:43 +11:00
port : port ,
2014-02-27 09:04:09 +11:00
udp4 : false ,
udp6 : false ,
2014-02-22 20:13:31 +11:00
log : log ,
server : false ,
sockets : [ ] ,
emit : emit ,
broadcast : broadcast ,
define : {
listen : {
'get.events.broadcasting' : 'does not require any special paramaters' ,
'get.events.listening' : 'does not require any special paramaters'
} ,
broadcast : {
'events.broadcasting' : 'data.events is a JSON object of event definitions by type ' + config . id + ' will broadcast on ' + path ,
2015-09-27 20:32:14 +10:00
'events.listening' : 'data.events is a JSON object of event definitions by type ' + config . id + ' is listening for on ' + path
2014-02-22 20:13:31 +11:00
}
} ,
onStart : function ( socket ) {
this . trigger (
'start' ,
socket
) ;
} ,
start : function ( ) {
if ( ! this . path ) {
2014-03-12 04:44:37 +11:00
server . log ( 'Socket Server Path not specified, refusing to start' . warn ) ;
2014-02-22 20:13:31 +11:00
return ;
}
2015-09-27 20:32:14 +10:00
2014-02-22 20:13:31 +11:00
fs . unlink (
2015-09-27 20:32:14 +10:00
this . path ,
2014-02-22 20:13:31 +11:00
(
function ( server ) {
return function ( ) {
2014-02-26 12:15:43 +11:00
server . log ( 'starting server on ' . debug , server . path . variable , ( ( server . port ) ? ':' + server . port : '' ) . variable ) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
if ( ! server . udp4 && ! server . udp6 ) {
2015-09-28 14:52:16 +10:00
if ( ! server . config . tls ) {
server . server = net . createServer (
serverCreated
) ;
} else {
server . log ( 'starting TLS server' . debug , server . config . tls ) ;
if ( server . config . tls . private ) {
server . config . tls . key = fs . readFileSync ( server . config . tls . private ) ;
2015-09-28 15:00:26 +10:00
} else {
server . config . tls . key = fs . readFileSync ( _ _dirname + '/../local-node-ipc-certs/private/server.key' ) ;
2015-09-28 14:52:16 +10:00
}
if ( server . config . tls . public ) {
server . config . tls . cert = fs . readFileSync ( server . config . tls . public ) ;
2015-09-28 15:00:26 +10:00
} else {
server . config . tls . cert = fs . readFileSync ( _ _dirname + '/../local-node-ipc-certs/server.pub' ) ;
2015-09-28 14:52:16 +10:00
}
if ( server . config . tls . dhparam ) {
server . config . tls . dhparam = fs . readFileSync ( server . config . tls . dhparam ) ;
}
if ( server . config . tls . trustedConnections ) {
if ( typeof server . config . tls . trustedConnections === 'string' ) {
server . config . tls . trustedConnections = [ server . config . tls . trustedConnections ] ;
}
server . config . tls . ca = [ ] ;
for ( var i = 0 ; i < server . config . tls . trustedConnections . length ; i ++ ) {
server . config . tls . ca . push (
fs . readFileSync ( server . config . tls . trustedConnections [ i ] )
) ;
}
}
server . server = tls . createServer (
server . config . tls ,
serverCreated
) ;
}
2014-02-27 09:04:09 +11:00
} else {
function UDPWrite ( message , socket ) {
var data = new Buffer ( message , server . config . encoding ) ;
server . server . send (
2015-09-27 20:32:14 +10:00
data ,
0 ,
data . length ,
socket . port ,
socket . address ,
2014-02-27 09:04:09 +11:00
function ( err , bytes ) {
if ( err ) {
2014-02-22 20:13:31 +11:00
server . trigger (
2015-09-27 20:32:14 +10:00
'error' ,
2014-02-27 09:04:09 +11:00
function ( err ) {
server . trigger ( 'error' , err ) ;
}
) ;
2014-02-22 20:13:31 +11:00
}
}
) ;
}
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
server . server = dgram . createSocket (
( ( server . udp4 ) ? 'udp4' : 'udp6' )
) ;
server . server . write = UDPWrite ;
server . server . on (
2015-09-27 20:32:14 +10:00
'listening' ,
2014-02-27 09:04:09 +11:00
function ( ) {
serverCreated ( server . server )
}
) ;
}
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
function serverCreated ( socket ) {
2014-03-12 04:37:37 +11:00
server . sockets . push ( socket ) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
if ( socket . setEncoding )
socket . setEncoding ( server . config . encoding ) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
server . log ( '## socket connection to server detected ##' . rainbow ) ;
socket . on (
'close' ,
function ( socket ) {
server . trigger (
'close' ,
socket
) ;
}
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
socket . on (
2015-09-27 20:32:14 +10:00
'error' ,
2014-02-27 09:04:09 +11:00
function ( err ) {
server . trigger ( 'error' , err ) ;
}
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
socket . on (
'data' ,
function ( data , UDPSocket ) {
2015-08-23 15:46:55 +10:00
var sock = ( ( server . udp4 || server . udp6 ) ? UDPSocket : socket ) ;
if ( server . config . rawBuffer ) {
data = new Buffer ( data , this . encoding ) ;
server . trigger (
'data' ,
data ,
sock
) ;
return ;
}
2014-03-04 07:02:56 +11:00
if ( ! this . ipcBuffer )
this . ipcBuffer = '' ;
2015-08-23 15:46:55 +10:00
2014-03-04 07:02:56 +11:00
data = ( this . ipcBuffer += data ) ;
2015-09-27 20:32:14 +10:00
2015-08-12 03:11:29 +10:00
if ( data . slice ( - 1 ) != eventParser . delimiter || data . indexOf ( eventParser . delimiter ) == - 1 ) {
2014-09-05 17:17:08 +10:00
server . log ( 'Implementing larger buffer for this socket message. You may want to consider smaller messages' . notice ) ;
2014-03-04 07:02:56 +11:00
return ;
}
2015-09-27 20:32:14 +10:00
2014-03-04 07:02:56 +11:00
this . ipcBuffer = '' ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
data = eventParser . parse ( data ) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
while ( data . length > 0 ) {
2015-09-27 20:32:14 +10:00
var message = new Message ;
message . load ( data . shift ( ) ) ;
server . log ( 'received event of : ' . debug , message . type . data , message . data ) ;
if ( message . data . id )
sock . id = message . data . id ;
2014-02-27 09:04:09 +11:00
server . trigger (
2015-09-27 20:32:14 +10:00
message . type ,
message . data ,
2014-02-27 09:04:09 +11:00
sock
2015-08-23 15:46:55 +10:00
) ;
2014-02-27 09:04:09 +11:00
}
}
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
socket . on (
'message' ,
function ( msg , rinfo ) {
2014-02-28 07:31:40 +11:00
if ( ! rinfo )
return ;
2014-02-27 09:04:09 +11:00
server . log ( 'Received UDP message from ' . debug , rinfo . address . variable , rinfo . port ) ;
2015-08-23 15:46:55 +10:00
var data ;
if ( server . config . rawSocket ) {
data = new Buffer ( msg , this . encoding ) ;
} else {
data = msg . toString ( ) ;
}
socket . emit ( 'data' , data , rinfo ) ;
2014-02-27 09:04:09 +11:00
}
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
server . trigger (
'connect' ,
socket
) ;
2015-09-27 20:32:14 +10:00
2015-08-23 15:46:55 +10:00
if ( server . config . rawBuffer ) {
return ;
}
2014-02-27 09:04:09 +11:00
server . trigger (
'get.events.broadcasting' ,
socket
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
server . trigger (
'get.events.listening' ,
socket
) ;
}
2015-09-27 20:32:14 +10:00
2014-02-26 12:15:43 +11:00
function started ( socket ) {
server . onStart ( socket )
}
2015-09-27 20:32:14 +10:00
2014-02-26 12:15:43 +11:00
if ( ! port ) {
2015-09-27 21:45:57 +10:00
server . log ( 'starting server as' . debug , 'Unix || Windows Socket' . variable ) ;
if ( process . platform === 'win32' ) {
server . path = server . path . replace ( /^\// , '' ) ;
server . path = server . path . replace ( /\//g , '-' ) ;
server . path = '\\\\.\\pipe\\' + server . path ;
}
2014-02-26 12:15:43 +11:00
server . server . listen (
server . path ,
started
) ;
2015-09-27 20:32:14 +10:00
2014-02-26 12:15:43 +11:00
server . server . maxConnections = server . maxConnections ;
return ;
}
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
if ( ! server . udp4 && ! server . udp4 ) {
2015-09-28 14:52:16 +10:00
server . log ( 'starting server as' . debug , ( server . config . tls ? 'TLS' : 'TCP' ) . variable ) ;
2014-02-27 09:04:09 +11:00
server . server . listen (
server . port ,
server . path ,
started
) ;
return ;
}
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
server . log ( 'starting server as' . debug , ( ( server . udp4 ) ? 'udp4' : 'udp6' ) . variable ) ;
server . server . bind (
2015-09-27 20:32:14 +10:00
server . port ,
2014-02-27 09:04:09 +11:00
server . path
) ;
2015-09-27 20:32:14 +10:00
2014-02-27 09:04:09 +11:00
started (
{
address : server . path ,
port : server . port
}
2014-02-22 20:13:31 +11:00
) ;
}
}
) ( this )
) ;
}
} ;
2015-09-27 20:32:14 +10:00
2014-02-22 20:13:31 +11:00
new pubsub ( server ) ;
2015-09-27 20:32:14 +10:00
2014-02-22 20:13:31 +11:00
server . on (
'get.events.broadcasting' ,
function ( socket ) {
server . emit (
socket ,
'events.broadcasting' ,
{
id : server . config . id ,
events : server . define . broadcast
}
) ;
}
) ;
2015-09-27 20:32:14 +10:00
2014-02-22 20:13:31 +11:00
server . on (
'get.events.listening' ,
function ( socket ) {
server . emit (
socket ,
'events.listening' ,
{
id : server . config . id ,
events : server . define . listen ,
}
) ;
}
2015-09-27 20:32:14 +10:00
)
2014-02-22 20:13:31 +11:00
server . on (
2015-09-27 20:32:14 +10:00
'close' ,
2014-02-22 20:13:31 +11:00
function ( ) {
for ( var i = 0 , count = server . sockets . length ; i < count ; i ++ ) {
var socket = server . sockets [ i ] ;
2014-09-03 13:48:05 +10:00
var destroyedSocketId = false ;
2015-09-27 20:32:14 +10:00
2014-03-01 21:30:26 +11:00
if ( socket ) {
2015-09-27 20:32:14 +10:00
if ( socket . readable )
continue ;
2014-03-01 21:30:26 +11:00
}
2015-09-27 20:32:14 +10:00
2014-08-28 13:57:37 +10:00
if ( socket . id )
destroyedSocketId = socket . id ;
2015-09-27 20:32:14 +10:00
2014-08-28 13:57:37 +10:00
server . log ( 'socket disconnected' . notice , ' ' + destroyedSocketId . variable ) ;
2014-08-27 13:15:53 +10:00
2014-03-01 21:30:26 +11:00
if ( socket )
socket . destroy ( ) ;
2015-09-27 20:32:14 +10:00
2014-03-01 21:30:26 +11:00
server . sockets . splice ( i , 1 ) ;
2014-08-27 13:15:53 +10:00
2014-08-28 13:57:37 +10:00
server . trigger ( 'socket.disconnected' , socket , destroyedSocketId ) ;
2014-08-27 13:15:53 +10:00
2014-02-22 20:13:31 +11:00
return ;
}
2015-09-27 20:32:14 +10:00
}
2014-08-28 13:41:12 +10:00
) ;
2014-02-22 20:13:31 +11:00
return server ;
}
2014-02-28 07:31:40 +11:00
module . exports = init ;