madeline-ton
Version:
Pure JS client-side implementation of the Telegram TON blockchain protocol
204 lines (166 loc) • 6.47 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _random = require("../crypto-sync/random");
var _constants = require("../TL/constants");
var _stream = _interopRequireDefault(require("../TL/stream"));
var _tools = require("../tools");
var Websocket =
/*#__PURE__*/
function () {
function Websocket() {
(0, _classCallCheck2["default"])(this, Websocket);
}
(0, _createClass2["default"])(Websocket, [{
key: "connect",
/**
*
* @param {Context} ctx Connection context
*/
value: function () {
var _connect = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee2(ctx) {
var _this = this;
var random, byteView, reverse, key, keyRev, iv, ivRev;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
this.crypto = ctx.getCrypto();
random = new Uint32Array(16);
byteView = new Uint8Array(random.buffer);
do {
(0, _random.fastRandom)(random);
} while (byteView[0] === 0xEF || _constants.obf2.includes(random[0]) || random[1] === 0);
random[14] = 0xefefefef;
reverse = new Uint32Array(byteView.slice().reverse().buffer);
key = random.slice(2, 10);
keyRev = reverse.slice(2, 10);
iv = random.slice(10, 14);
ivRev = reverse.slice(10, 14);
_context2.next = 12;
return this.crypto.getCtr(key, iv);
case 12:
this.encrypt = _context2.sent;
_context2.next = 15;
return this.crypto.getCtr(keyRev, ivRev);
case 15:
this.decrypt = _context2.sent;
_context2.t0 = random;
_context2.t1 = Uint32Array;
_context2.next = 20;
return this.encrypt.process(random);
case 20:
_context2.t2 = _context2.sent;
_context2.t3 = new _context2.t1(_context2.t2).slice(14, 16);
_context2.t0.set.call(_context2.t0, _context2.t3, 14);
_context2.next = 25;
return new Promise(function (resolve, reject) {
_this.socket = new WebSocket(ctx.getUri('ws'));
_this.socket.binaryType = "arraybuffer";
_this.socket.onmessage =
/*#__PURE__*/
function () {
var _ref = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee(message) {
var length;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.t0 = Uint8Array;
_context.next = 3;
return _this.decrypt.process(new Uint8Array(message.data));
case 3:
_context.t1 = _context.sent;
message = new _context.t0(_context.t1);
length = message[0];
length = (length >= 0x7f ? message[1] | message[2] << 8 | message[3] << 16 : length) << 2; //console.log(message.length - 1, length)
_this.onMessage(new _stream["default"](message.slice(-length).buffer));
case 8:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return function (_x2) {
return _ref.apply(this, arguments);
};
}();
_this.socket.onopen = resolve;
_this.socket.onerror = reject;
_this.socket.onclose = _this.close.bind(_this);
});
case 25:
this.socket.onerror = function (e) {
console.log("Websocket error: ", e);
_this.close();
};
return _context2.abrupt("return", this.socket.send(random));
case 27:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function connect(_x) {
return _connect.apply(this, arguments);
}
return connect;
}()
}, {
key: "write",
value: function write(payload) {
var _this2 = this;
var length = payload.uBuf.length - 1;
if (length >= 0x7f) {
payload.pos = 0;
payload.writeUnsignedInt(length << 8 & 0x7F);
payload = payload.bBuf;
} else {
payload = payload.bBuf.slice(3);
payload[0] = length;
}
return this.encrypt.process(payload).then(function (payload) {
return _this2.socket.send(payload);
});
}
}, {
key: "getBuffer",
value: function getBuffer(length) {
var s = new _stream["default"](new Uint32Array(6 + (length || 0)));
s.pos += 6;
s.initPos = 1;
return s;
}
}, {
key: "close",
value: function close() {
console.log("Closing socket!");
if (this.socket) {
this.socket.close();
this.socket = undefined;
this.onClose();
}
}
}, {
key: "isHttp",
value: function isHttp() {
return false;
}
}]);
return Websocket;
}();
var _default = Websocket;
exports["default"] = _default;