fox-wamp
Version:
Web Application Message Router/Server WAMP/MQTT
151 lines (126 loc) • 4.3 kB
JavaScript
const net = require('net')
const msgpack = require('msgpack-lite')
const { SESSION_DEBUG } = require('../messages')
const { HyperSocketFormatter, RemoteHyperClient } = require('./client')
function HyperNetWriter (socket, session, router) {
this.hyperPkgWrite = (msg, callback) => {
const pkg = msgpack.encode(msg)
// router.emit(SESSION_TX, session, pkg)
socket.write(pkg, callback)
}
this.hyperPkgClose = (code, reason) => {
router.emit(SESSION_DEBUG, session, 'Closing NetSocket connection: [' + code + '] ' + reason)
socket.end()
}
}
/** HyperNetServer is a server for HyperNet protocol over TCP.
* @param {hyper/gate} gate - the gate instance
* @param {net.Server} options - options for the net.Server
* @param {number} options.port - port to listen on
* @returns {net.Server}
*/
function listenHyperNetServer (gate, options) {
const router = gate.getRouter()
const _server = net.Server(function (socket) {
const session = router.createSession()
session.setGateProtocol('hyper.net')
const socketWriter = new HyperNetWriter(socket, session, router)
const decodeStream = msgpack.createDecodeStream()
socket.pipe(decodeStream).on('data', function (msg) {
const ctx = gate.createContext(session, socketWriter)
// ctx.emit(SESSION_RX, msg)
gate.handle(ctx, session, msg)
})
socket.on('end', function () {
console.log('event:socket-end')
})
socket.on('close', function () {
router.removeSession(session)
})
socket.on('error', function (exc) {
console.log("ignoring exception:" + exc, session.getSid())
})
})
_server.listen(options)
return _server
}
/** HyperNetClient is a client for HyperNet protocol over TCP.
* param {Object} params - configuration parameters
* @param {string} params.host - host to connect to
* @param {number} params.port - port to connect to
* @param {number} [params.maxReconnectAttempts=-1] - maximum number of reconnect attempts, -1 means infinite
* @param {number} [params.reconnectDelay=1000] - delay between reconnect attempts in milliseconds
*/
function HyperNetClient (params) {
const socket = new net.Socket()
const socketWriter = new HyperNetWriter(socket, null, this)
const formater = new HyperSocketFormatter(socketWriter)
RemoteHyperClient.call(this, formater)
const decoder = new msgpack.Decoder()
decoder.on('data', (msg) => {
formater.onMessage(msg)
})
const conf = params || {}
let reconnectAttempts = 0
let maxReconnectAttempts = conf.maxReconnectAttempts || -1
let reconnectDelay = conf.reconnectDelay || 1000
let isClosing = false
socket.on('connect', () => {
console.log('HyperNetClient:Connection established', conf)
reconnectAttempts = 0
if (typeof socket._connectResolve === 'function') {
socket._connectResolve(this)
socket._connectResolve = null
}
this.applyOnOpen()
})
const doConnect = (resolve, reject) => {
socket._connectResolve = resolve
socket.connect(conf.port, conf.host)
}
socket.on('error', (err) => {
if (isClosing) return
console.log('HyperNetClient:Connection ERROR', err)
})
this.connect = () => {
isClosing = false
return new Promise((resolve, reject) => {
doConnect(resolve, reject)
})
}
socket.on('timeout', () => {
console.log('HyperNetClient:Connection timeout')
})
socket.on('drain', () => {
console.log('HyperNetClient:Socket drained')
})
socket.on('data', (chunk) => {
decoder.decode(chunk)
})
socket.on('close', () => {
console.log('HyperNetClient:Connection closed')
if (isClosing) return
if (maxReconnectAttempts < 0 || reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++
console.log('Reconnecting...', conf)
setTimeout(() => {
this.connect().catch(() => {})
}, reconnectDelay)
}
})
socket.on('end', () => {
console.log('HyperNetClient:Connection ended')
})
this.close = function () {
isClosing = true
socket.end()
}
this.getSocket = function () {
return socket
}
this.emit = () => {}
}
exports.listenHyperNetServer = listenHyperNetServer
exports.HyperNetWriter = HyperNetWriter
exports.HyperNetClient = HyperNetClient