UNPKG

node-quic

Version:

A wrapper around fidm/quic, node-quic is a dead simple stream based QUIC server / client for use in node.js.

152 lines (116 loc) 5.41 kB
'use strict'; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _quic = require('quic'); var _arbitraryPromise = require('arbitrary-promise'); var _arbitraryPromise2 = _interopRequireDefault(_arbitraryPromise); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // simple convenience helper var rejectPromise = function rejectPromise(promise, err, message) { promise.reject(Object.assign(err, { class: message })); }; // the underlying quic library can only handle strings or buffers. // This is used to convert to one of them. var convertToSendType = function convertToSendType(data) { // buffers should be sendable if (Buffer.isBuffer(data)) return data; // objects must be stringified if ((typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') return JSON.stringify(data); // all else should be strings return data; }; var Quic = function () { function Quic() { _classCallCheck(this, Quic); } _createClass(Quic, [{ key: 'listen', value: function listen(port) { var address = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'localhost'; var promise = new _arbitraryPromise2.default([['resolve', 'then'], ['reject', 'onError'], ['handleData', 'onData']]); if (!port) return promise.reject('must supply port argument!'); this._server = new _quic.Server(); this._server.on('error', function (err) { return rejectPromise(promise, err, 'server error'); }).on('session', function (session) { session.on('error', function (err) { return rejectPromise(promise, err, 'server session error'); }).on('stream', function (stream) { var message = ''; var buffer = void 0; stream.on('error', function (err) { return rejectPromise(promise, err, 'server stream error'); }).on('data', function (data) { message += data.toString(); if (buffer) buffer = Buffer.concat([buffer, data]);else buffer = data; }).on('end', function () { var oldWrite = stream.write.bind(stream); stream.write = function (data) { var convertedData = convertToSendType(data); oldWrite(convertedData); stream.end(); }; promise.handleData(message, stream, buffer); }); }); }); this._server.listen(port, address).then(promise.resolve).catch(promise.reject); return promise; } }, { key: 'stopListening', value: async function stopListening() { // TODO returned promise to return onError instead of catch this._server && (await this._server.close()); delete this._server; } }, { key: 'getServer', value: function getServer() { return this._server; } }, { key: 'getAddress', value: function getAddress() { var defaul = { port: 0, family: '', address: '' }; return this._server && this._server.address() || defaul; } }, { key: 'send', value: function send(port, address, data) { var promise = new _arbitraryPromise2.default([['resolve', 'then'], ['reject', 'onError'], ['handleData', 'onData']]); if (!port || !address || !data) return promise.reject('must supply three parameters'); var convertedData = convertToSendType(data); var client = new _quic.Client(); client.on('error', function (err) { rejectPromise(promise, err, 'client error'); }); // These clients are ephemeral so we'll nuke em when they're done client.on('close', function () { return client.destroy(); }); client.connect(port, address).then(function () { var stream = client.request(); var message = ''; var buffer = void 0; stream.on('error', function (err) { return rejectPromise(promise, err, 'client stream error'); }).on('data', function (data) { message += data.toString(); if (buffer) buffer = Buffer.concat([buffer, data]);else buffer = data; }).on('end', function () { client.close(); promise.handleData(message, buffer); }); stream.write(convertedData, function () { promise.resolve(); stream.end(); }); }); return promise; } }]); return Quic; }(); module.exports = new Quic();