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
JavaScript
;
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();