123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- const TcpClient = require("./TcpClient");
- const crc = require('crc');
- class TcpTransport {
- constructor(ipAddress, port) {
- this.tcpClient = new TcpClient();
- this.sendCounter = 0;
- this.ipAddress = ipAddress;
- this.port = port;
- }
- async connect() {
- await this.tcpClient.connect(this.ipAddress, this.port);
- }
- /**
- * Sends the given packet (bytes array) to the connected peer
- * Original reference: https://core.telegram.org/mtproto#tcp-transport
- * The packets are encoded as: total length, sequence number, packet and checksum (CRC32)
- * @param packet
- */
- send(packet) {
- if (this.tcpClient.connected) {
- throw Error("not connected");
- }
- let buffer = Buffer.alloc(4 + 4);
- buffer.writeInt32LE(packet.length + 12, 0);
- buffer.writeInt32LE(this.sendCounter, 4);
- buffer = Buffer.concat([buffer, packet]);
- let tempBuffer = Buffer.alloc(4);
- tempBuffer.writeUInt32LE(crc.crc32(buffer), 0);
- buffer = Buffer.concat([buffer, tempBuffer]);
- this.tcpClient.write(buffer);
- this.sendCounter++;
- }
- /**
- * Receives a TCP message (tuple(sequence number, body)) from the connected peer
- * @returns {{body: {Buffer}, seq: {Buffer}}}
- */
- receive() {
- /**First read everything we need**/
- let packetLengthBytes = this.tcpClient.read(4);
- let packetLength = Buffer.from(packetLengthBytes).readInt32LE(0);
- let seqBytes = this.tcpClient.read(4);
- let seq = Buffer.from(seqBytes).readInt32LE(0);
- let body = this.tcpClient.read(packetLength - 12);
- let checksum = Buffer.from(this.tcpClient.read(4)).readUInt32LE(0);
- /**Then perform the checks**/
- let rv = Buffer.concat([packetLengthBytes, seqBytes, body]);
- let validChecksum = crc.crc32(rv);
- if (checksum !== validChecksum) {
- throw Error("invalid checksum");
- }
- /** If we passed the tests, we can then return a valid TCP message**/
- return {seq, body}
- }
- close() {
- if (this.tcpClient.connected) {
- this.tcpClient.close();
- }
- }
- /**
- * Cancels (stops) trying to receive from the
- * remote peer and raises an {Error}
- */
- cancelReceive() {
- this.tcpClient.cancelRead();
- }
- /**
- * Gets the client read delay
- * @returns {number}
- */
- getClientDelay() {
- return this.tcpClient.delay;
- }
- }
- module.exports = TcpTransport;
|