UNPKG

scalra

Version:

node.js framework to prototype and scale rapidly

187 lines (147 loc) 5.33 kB
// // connector.js // // a socket initiator to a remote host // // history: // 2013-09-14 adopted from frontier /* functions: addHandler(handlers) connect(ip_port, onDone) disconnect(onDone) isConnectorReady() send(packet_type, para, expected_response, onResponse) dispose(onDone) config: { name: 'string', // name of connector (used to get handlers) onConnect: 'function', // optional connection handler onDisconnect: 'function', // optional disconnection handler eventHandler: 'object' // optional event handler (currently unused) } */ exports.icConnector = function (config) { // check required parameters if (config === undefined) config = {}; if (typeof config.onConnect !== 'function' && typeof config.onDisconnect !== 'function') LOG.warn('no connection handlers specified in config, connect/disconnect event may not be notified', 'SR.Connector'); // // local variables // // a node.js connection (socket) object var l_socket = undefined; // a connection object encapsulating the socket (used for send messages) var l_conn = undefined; // use a provided, existing event handler set (if name is provided in config), or a new one var l_eventHandler = SR.Handler.get(config.name); // init connection handler // external app to call when establishing new connection var l_connHandler = new SR.Conn.ConnHandler(config); // socket handler (handling new socket connections) var l_socketHandler = new SR.Socket(l_connHandler, l_eventHandler); // // public functions // // store a handler for incoming events // handlers should provide the following properties: // 'handlers' // 'checkers' // // or these methods: // 'getFormatCheckers' // 'getMessageHandlers' // return # of handlers added var l_addHandler = this.addHandler = function (handlers) { // perform loading of checkers & handlers var num = l_eventHandler.load(handlers); LOG.sys('adding ' + num + ' handlers', 'SR.Connector.addHandler'); return num; }; // start processing // onDone: { // err: 'object', // error object // endpoint: 'string' // string of the IP/port of the host // } this.connect = function (ip_port, onDone) { // shutdown first if already exists if (l_socket !== undefined) { try { l_socket.end(); } catch (e) { LOG.error('l_socket.end() exception-' + e, 'SR.Connector'); } } try { LOG.warn('init a connection to: ' + ip_port.IP + ':' + ip_port.port + '...', 'SR.Connector'); l_socket = SR.net.createConnection(ip_port.port, ip_port.IP, function () { // this callback is called when 'connection' event is fired l_socket.connected = true; // store remote address & port // NOTE: because l_socket.remoteAddress doesn't exist l_socket.host = ip_port.IP; l_socket.port = ip_port.port; // setup socket's various properties & handling methods // NOTE: after setup the socket will receive a connID l_socketHandler.setup(l_socket); // record connection object for later use // TODO: can we simply record & use l_conn instead of l_socket? l_conn = SR.Conn.getConnObject(l_socket.connID); LOG.sys('outgoing connection: ' + l_socket.host + ':' + l_socket.port, 'SR.Connector'); UTIL.safeCall(onDone, undefined, l_socket); }); l_socket.on('error', function (e) { LOG.error('socket connection error: ', 'SR.Connector'); LOG.error(e); UTIL.safeCall(onDone, e); }); } catch (e) { LOG.error('connector exception-' + e, 'SR.Connector'); l_disconnect(onDone, e); } }; //----------------------------------------- // shutdown all connected sockets (clients) // NOTE: this can also be called from outside via 'dispose' method var l_disconnect = this.disconnect = function (onDone) { // shutdown connector, if exist if (l_socket === undefined) return UTIL.safeCall(onDone); try { l_socket.on('close', function (err) { if (err) LOG.warn('connection to [' + l_socket.host + ':' + l_socket.port + '] was closed with error'); // call callback when connection is fully closed }); l_socket.end(); l_socket = undefined; } catch (e) { LOG.error('l_socket.end() exception-'+e, 'SR.Connector'); l_socket = undefined; } UTIL.safeCall(onDone); }; // check whether connector has successfully connected to remote server this.isConnectorReady = function () { return (l_socket !== undefined && l_socket.connected); }; // // Connector methods // // send something to remote host this.send = function (packet_type, para, expected_response, onResponse) { // see if we need to register responder // TODO: hide _cid attachment to EventManager var cid = l_eventHandler.addResponder(expected_response, onResponse); // send out message if (l_conn) SR.EventManager.send(packet_type, para, [l_conn], cid); else LOG.error('no outgoing connection established, cannot send', 'SR.Connector'); }; // end this connector this.dispose = function (onDone) { LOG.warn('dispose called...', 'SR.Connector'); l_disconnect(onDone); }; }; // end icConnector