emailjs-tcp-socket
Version:
This shim brings the W3C Raw Socket API to node.js and Chromium. Its purpose is to enable apps to use the same api in Firefox OS, Chrome OS, and on the server.
173 lines (143 loc) • 15.4 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
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 _ramda = require('ramda');
var _tlsUtils = require('./tls-utils');
var _tlsUtils2 = _interopRequireDefault(_tlsUtils);
var _workerUtils = require('./worker-utils');
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"); } }
var TCPSocket = function () {
_createClass(TCPSocket, null, [{
key: 'open',
value: function open(host, port) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return new TCPSocket({ host: host, port: port, options: options });
}
}]);
function TCPSocket(_ref) {
var _this = this;
var host = _ref.host,
port = _ref.port,
options = _ref.options;
_classCallCheck(this, TCPSocket);
this.host = host;
this.port = port;
this.ssl = false;
this.bufferedAmount = 0;
this.readyState = 'connecting';
this.binaryType = (0, _ramda.propOr)('arraybuffer', 'binaryType')(options);
if (this.binaryType !== 'arraybuffer') {
throw new Error('Only arraybuffers are supported!');
}
this._ca = options.ca;
this._useTLS = (0, _ramda.propOr)(false, 'useSecureTransport')(options);
this._useSTARTTLS = false;
this._wsHost = (0, _ramda.pathOr)(window.location.origin, ['ws', 'url'])(options);
this._wsOptions = (0, _ramda.pathOr)({}, ['ws', 'options'])(options);
this._wsOptions.reconnection = this._wsOptions.reconnection || false;
this._wsOptions.multiplex = this._wsOptions.multiplex || false;
this._socket = io(this._wsHost, this._wsOptions);
this._socket.emit('open', { host: host, port: port }, function (proxyHostname) {
_this._proxyHostname = proxyHostname;
if (_this._useTLS) {
// the socket is up, do the tls handshake
(0, _tlsUtils2.default)(_this);
} else {
// socket is up and running
_this._emit('open', {
proxyHostname: _this._proxyHostname
});
}
_this._socket.on('data', function (buffer) {
if (_this._useTLS || _this._useSTARTTLS) {
// feed the data to the tls socket
if (_this._tlsWorker) {
_this._tlsWorker.postMessage((0, _workerUtils.createMessage)(_workerUtils.EVENT_INBOUND, buffer), [buffer]);
} else {
_this._tls.processInbound(buffer);
}
} else {
_this._emit('data', buffer);
}
});
_this._socket.on('error', function (message) {
_this._emit('error', new Error(message));
_this.close();
});
_this._socket.on('close', function () {
return _this.close();
});
});
}
_createClass(TCPSocket, [{
key: 'close',
value: function close() {
this.readyState = 'closing';
this._socket.emit('end');
this._socket.disconnect();
if (this._tlsWorker) {
this._tlsWorker.terminate();
}
this._emit('close');
}
}, {
key: 'send',
value: function send(buffer) {
if (this._useTLS || this._useSTARTTLS) {
// give buffer to forge to be prepared for tls
if (this._tlsWorker) {
this._tlsWorker.postMessage((0, _workerUtils.createMessage)(_workerUtils.EVENT_OUTBOUND, buffer), [buffer]);
} else {
this._tls.prepareOutbound(buffer);
}
return;
}
this._send(buffer);
}
}, {
key: '_send',
value: function _send(data) {
var _this2 = this;
this._socket.emit('data', data, function () {
return _this2._emit('drain');
});
}
}, {
key: 'upgradeToSecure',
value: function upgradeToSecure() {
if (this.ssl || this._useSTARTTLS) return;
this._useSTARTTLS = true;
(0, _tlsUtils2.default)(this);
}
}, {
key: '_emit',
value: function _emit(type, data) {
var target = this;
switch (type) {
case 'open':
this.readyState = 'open';
this.onopen && this.onopen({ target: target, type: type, data: data });
break;
case 'error':
this.onerror && this.onerror({ target: target, type: type, data: data });
break;
case 'data':
this.ondata && this.ondata({ target: target, type: type, data: data });
break;
case 'drain':
this.ondrain && this.ondrain({ target: target, type: type, data: data });
break;
case 'close':
this.readyState = 'closed';
this.onclose && this.onclose({ target: target, type: type, data: data });
break;
}
}
}]);
return TCPSocket;
}();
exports.default = TCPSocket;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9zb2NrZXRpby1zb2NrZXQuanMiXSwibmFtZXMiOlsiVENQU29ja2V0IiwiaG9zdCIsInBvcnQiLCJvcHRpb25zIiwic3NsIiwiYnVmZmVyZWRBbW91bnQiLCJyZWFkeVN0YXRlIiwiYmluYXJ5VHlwZSIsIkVycm9yIiwiX2NhIiwiY2EiLCJfdXNlVExTIiwiX3VzZVNUQVJUVExTIiwiX3dzSG9zdCIsIndpbmRvdyIsImxvY2F0aW9uIiwib3JpZ2luIiwiX3dzT3B0aW9ucyIsInJlY29ubmVjdGlvbiIsIm11bHRpcGxleCIsIl9zb2NrZXQiLCJpbyIsImVtaXQiLCJfcHJveHlIb3N0bmFtZSIsInByb3h5SG9zdG5hbWUiLCJfZW1pdCIsIm9uIiwiX3Rsc1dvcmtlciIsInBvc3RNZXNzYWdlIiwiYnVmZmVyIiwiX3RscyIsInByb2Nlc3NJbmJvdW5kIiwibWVzc2FnZSIsImNsb3NlIiwiZGlzY29ubmVjdCIsInRlcm1pbmF0ZSIsInByZXBhcmVPdXRib3VuZCIsIl9zZW5kIiwiZGF0YSIsInR5cGUiLCJ0YXJnZXQiLCJvbm9wZW4iLCJvbmVycm9yIiwib25kYXRhIiwib25kcmFpbiIsIm9uY2xvc2UiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7O0FBQ0E7Ozs7QUFDQTs7Ozs7O0lBS3FCQSxTOzs7eUJBQ05DLEksRUFBTUMsSSxFQUFvQjtBQUFBLFVBQWRDLE9BQWMsdUVBQUosRUFBSTs7QUFDckMsYUFBTyxJQUFJSCxTQUFKLENBQWMsRUFBRUMsVUFBRixFQUFRQyxVQUFSLEVBQWNDLGdCQUFkLEVBQWQsQ0FBUDtBQUNEOzs7QUFFRCwyQkFBc0M7QUFBQTs7QUFBQSxRQUF2QkYsSUFBdUIsUUFBdkJBLElBQXVCO0FBQUEsUUFBakJDLElBQWlCLFFBQWpCQSxJQUFpQjtBQUFBLFFBQVhDLE9BQVcsUUFBWEEsT0FBVzs7QUFBQTs7QUFDcEMsU0FBS0YsSUFBTCxHQUFZQSxJQUFaO0FBQ0EsU0FBS0MsSUFBTCxHQUFZQSxJQUFaO0FBQ0EsU0FB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QUtNLE9BQUwsSUFBZ0IsS0FBS0EsT0FBTCxDQUFhLEVBQUVKLGNBQUYsRUFBVUQsVUFBVixFQUFnQkQsVUFBaEIsRUFBYixDQUFoQjtBQUNBO0FBQ0YsYUFBSyxPQUFMO0FBQ0UsZUFBS2hDLFVBQUwsR0FBa0IsUUFBbEI7QUFDQSxlQUFLdUMsT0FBTCxJQUFnQixLQUFLQSxPQUFMLENBQWEsRUFBRUwsY0FBRixFQUFVRCxVQUFWLEVBQWdCRCxVQUFoQixFQUFiLENBQWhCO0FBQ0E7QUFqQko7QUFtQkQ7Ozs7OztrQkF4SGtCdEMsUyIsImZpbGUiOiJzb2NrZXRpby1zb2NrZXQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwYXRoT3IsIHByb3BPciB9IGZyb20gJ3JhbWRhJ1xuaW1wb3J0IGNyZWF0ZVRscyBmcm9tICcuL3Rscy11dGlscydcbmltcG9ydCB7XG4gIEVWRU5UX0lOQk9VTkQsIEVWRU5UX09VVEJPVU5ELFxuICBjcmVhdGVNZXNzYWdlXG59IGZyb20gJy4vd29ya2VyLXV0aWxzJ1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUQ1BTb2NrZXQge1xuICBzdGF0aWMgb3BlbiAoaG9zdCwgcG9ydCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBUQ1BTb2NrZXQoeyBob3N0LCBwb3J0LCBvcHRpb25zIH0pXG4gIH1cblxuICBjb25zdHJ1Y3RvciAoeyBob3N0LCBwb3J0LCBvcHRpb25zIH0pIHtcbiAgICB0aGlzLmhvc3QgPSBob3N0XG4gICAgdGhpcy5wb3J0ID0gcG9ydFxuICAgIHRoaXMuc3NsID0gZmFsc2VcbiAgICB0aGlzLmJ1ZmZlcmVkQW1vdW50ID0gMFxuICAgIHRoaXMucmVhZHlTdGF0ZSA9ICdjb25uZWN0aW5nJ1xuICAgIHRoaXMuYmluYXJ5VHlwZSA9IHByb3BPcignYXJyYXlidWZmZXInLCAnYmluYXJ5VHlwZScpKG9wdGlvbnMpXG5cbiAgICBpZiAodGhpcy5iaW5hcnlUeXBlICE9PSAnYXJyYXlidWZmZXInKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgYXJyYXlidWZmZXJzIGFyZSBzdXBwb3J0ZWQhJylcbiAgICB9XG5cbiAgICB0aGlzLl9jYSA9IG9wdGlvbnMuY2FcbiAgICB0aGlzLl91c2VUTFMgPSBwcm9wT3IoZmFsc2UsICd1c2VTZWN1cmVUcmFuc3BvcnQnKShvcHRpb25zKVxuICAgIHRoaXMuX3VzZVNUQVJUVExTID0gZmFsc2VcblxuICAgIHRoaXMuX3dzSG9zdCA9IHBhdGhPcih3aW5kb3cubG9jYXRpb24ub3JpZ2luLCBbJ3dzJywgJ3VybCddKShvcHRpb25zKVxuICAgIHRoaXMuX3dzT3B0aW9ucyA9IHBhdGhPcih7fSwgWyd3cycsICdvcHRpb25zJ10pKG9wdGlvbnMpXG4gICAgdGhpcy5fd3NPcHRpb25zLnJlY29ubmVjdGlvbiA9IHRoaXMuX3dzT3B0aW9ucy5yZWNvbm5lY3Rpb24gfHwgZmFsc2VcbiAgICB0aGlzLl93c09wdGlvbnMubXVsdGlwbGV4ID0gdGhpcy5fd3NPcHRpb25zLm11bHRpcGxleCB8fCBmYWxzZVxuXG4gICAgdGhpcy5fc29ja2V0ID0gaW8odGhpcy5fd3NIb3N0LCB0aGlzLl93c09wdGlvbnMpXG4gICAgdGhpcy5fc29ja2V0LmVtaXQoJ29wZW4nLCB7IGhvc3QsIHBvcnQgfSwgcHJveHlIb3N0bmFtZSA9PiB7XG4gICAgICB0aGlzLl9wcm94eUhvc3RuYW1lID0gcHJveHlIb3N0bmFtZVxuICAgICAgaWYgKHRoaXMuX3VzZVRMUykge1xuICAgICAgICAvLyB0aGUgc29ja2V0IGlzIHVwLCBkbyB0aGUgdGxzIGhhbmRzaGFrZVxuICAgICAgICBjcmVhdGVUbHModGhpcylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHNvY2tldCBpcyB1cCBhbmQgcnVubmluZ1xuICAgICAgICB0aGlzLl9lbWl0KCdvcGVuJywge1xuICAgICAgICAgIHByb3h5SG9zdG5hbWU6IHRoaXMuX3Byb3h5SG9zdG5hbWVcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc29ja2V0Lm9uKCdkYXRhJywgYnVmZmVyID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX3VzZVRMUyB8fCB0aGlzLl91c2VTVEFSVFRMUykge1xuICAgICAgICAgIC8vIGZlZWQgdGhlIGRhdGEgdG8gdGhlIHRscyBzb2NrZXRcbiAgICAgICAgICBpZiAodGhpcy5fdGxzV29ya2VyKSB7XG4gICAgICAgICAgICB0aGlzLl90bHNXb3JrZXIucG9zdE1lc3NhZ2UoY3JlYXRlTWVzc2FnZShFVkVOVF9JTkJPVU5ELCBidWZmZXIpLCBbYnVmZmVyXSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fdGxzLnByb2Nlc3NJbmJvdW5kKGJ1ZmZlcilcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5fZW1pdCgnZGF0YScsIGJ1ZmZlcilcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgdGhpcy5fc29ja2V0Lm9uKCdlcnJvcicsIG1lc3NhZ2UgPT4ge1xuICAgICAgICB0aGlzLl9lbWl0KCdlcnJvcicsIG5ldyBFcnJvcihtZXNzYWdlKSlcbiAgICAgICAgdGhpcy5jbG9zZSgpXG4gICAgICB9KVxuXG4gICAgICB0aGlzLl9zb2NrZXQub24oJ2Nsb3NlJywgKCkgPT4gdGhpcy5jbG9zZSgpKVxuICAgIH0pXG4gIH1cblxuICBjbG9zZSAoKSB7XG4gICAgdGhpcy5yZWFkeVN0YXRlID0gJ2Nsb3NpbmcnXG5cbiAgICB0aGlzLl9zb2NrZXQuZW1pdCgnZW5kJylcbiAgICB0aGlzLl9zb2NrZXQuZGlzY29ubmVjdCgpXG5cbiAgICBpZiAodGhpcy5fdGxzV29ya2VyKSB7XG4gICAgICB0aGlzLl90bHNXb3JrZXIudGVybWluYXRlKClcbiAgICB9XG5cbiAgICB0aGlzLl9lbWl0KCdjbG9zZScpXG4gIH1cblxuICBzZW5kIChidWZmZXIpIHtcbiAgICBpZiAodGhpcy5fdXNlVExTIHx8IHRoaXMuX3VzZVNUQVJUVExTKSB7XG4gICAgICAvLyBnaXZlIGJ1ZmZlciB0byBmb3JnZSB0byBiZSBwcmVwYXJlZCBmb3IgdGxzXG4gICAgICBpZiAodGhpcy5fdGxzV29ya2VyKSB7XG4gICAgICAgIHRoaXMuX3Rsc1dvcmtlci5wb3N0TWVzc2FnZShjcmVhdGVNZXNzYWdlKEVWRU5UX09VVEJPVU5ELCBidWZmZXIpLCBbYnVmZmVyXSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3Rscy5wcmVwYXJlT3V0Ym91bmQoYnVmZmVyKVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5fc2VuZChidWZmZXIpXG4gIH1cblxuICBfc2VuZCAoZGF0YSkge1xuICAgIHRoaXMuX3NvY2tldC5lbWl0KCdkYXRhJywgZGF0YSwgKCkgPT4gdGhpcy5fZW1pdCgnZHJhaW4nKSlcbiAgfVxuXG4gIHVwZ3JhZGVUb1NlY3VyZSAoKSB7XG4gICAgaWYgKHRoaXMuc3NsIHx8IHRoaXMuX3VzZVNUQVJUVExTKSByZXR1cm5cblxuICAgIHRoaXMuX3VzZVNUQVJUVExTID0gdHJ1ZVxuICAgIGNyZWF0ZVRscyh0aGlzKVxuICB9XG5cbiAgX2VtaXQgKHR5cGUsIGRhdGEpIHtcbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlICdvcGVuJzpcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gJ29wZW4nXG4gICAgICAgIHRoaXMub25vcGVuICYmIHRoaXMub25vcGVuKHsgdGFyZ2V0LCB0eXBlLCBkYXRhIH0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgIHRoaXMub25lcnJvciAmJiB0aGlzLm9uZXJyb3IoeyB0YXJnZXQsIHR5cGUsIGRhdGEgfSlcbiAgICAgICAgYnJlYWtcbiAgICAgIGNhc2UgJ2RhdGEnOlxuICAgICAgICB0aGlzLm9uZGF0YSAmJiB0aGlzLm9uZGF0YSh7IHRhcmdldCwgdHlwZSwgZGF0YSB9KVxuICAgICAgICBicmVha1xuICAgICAgY2FzZSAnZHJhaW4nOlxuICAgICAgICB0aGlzLm9uZHJhaW4gJiYgdGhpcy5vbmRyYWluKHsgdGFyZ2V0LCB0eXBlLCBkYXRhIH0pXG4gICAgICAgIGJyZWFrXG4gICAgICBjYXNlICdjbG9zZSc6XG4gICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9ICdjbG9zZWQnXG4gICAgICAgIHRoaXMub25jbG9zZSAmJiB0aGlzLm9uY2xvc2UoeyB0YXJnZXQsIHR5cGUsIGRhdGEgfSlcbiAgICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbn1cbiJdfQ==