StringSession.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. const MemorySession = require('./Memory')
  2. const AuthKey = require('../crypto/AuthKey')
  3. const BinaryReader = require('../extensions/BinaryReader')
  4. const CURRENT_VERSION = '1'
  5. class StringSession extends MemorySession {
  6. /**
  7. * This session file can be easily saved and loaded as a string. According
  8. * to the initial design, it contains only the data that is necessary for
  9. * successful connection and authentication, so takeout ID is not stored.
  10. * It is thought to be used where you don't want to create any on-disk
  11. * files but would still like to be able to save and load existing sessions
  12. * by other means.
  13. * You can use custom `encode` and `decode` functions, if present:
  14. * `encode` definition must be ``function encode(value: Buffer) -> string:``.
  15. * `decode` definition must be ``function decode(value: string) -> Buffer:``.
  16. * @param session {string|null}
  17. */
  18. constructor(session = null) {
  19. super()
  20. if (session) {
  21. if (session[0] !== CURRENT_VERSION) {
  22. throw new Error('Not a valid string')
  23. }
  24. session = session.slice(1)
  25. const ipLen = session.length === 352 ? 4 : 16
  26. const r = StringSession.decode(session)
  27. const reader = new BinaryReader(r)
  28. this._dcId = reader.read(1).readUInt8()
  29. const ip = reader.read(ipLen)
  30. this._port = reader.read(2).readInt16BE()
  31. const key = reader.read(-1)
  32. this._serverAddress = ip.readUInt8(0) + '.' +
  33. ip.readUInt8(1) + '.' + ip.readUInt8(2) +
  34. '.' + ip.readUInt8(3)
  35. if (key) {
  36. this._authKey = new AuthKey(key)
  37. }
  38. }
  39. }
  40. /**
  41. * @param x {Buffer}
  42. * @returns {string}
  43. */
  44. static encode(x) {
  45. return x.toString('base64')
  46. }
  47. /**
  48. * @param x {string}
  49. * @returns {Buffer}
  50. */
  51. static decode(x) {
  52. return Buffer.from(x, 'base64')
  53. }
  54. save() {
  55. if (!this.authKey) {
  56. return ''
  57. }
  58. const ip = this.serverAddress.split('.')
  59. const dcBuffer = Buffer.from([this.dcId])
  60. const ipBuffer = Buffer.alloc(4)
  61. const portBuffer = Buffer.alloc(2)
  62. portBuffer.writeInt16BE(this.port)
  63. for (let i = 0; i < ip.length; i++) {
  64. ipBuffer.writeUInt8(parseInt(ip[i]), i)
  65. }
  66. return CURRENT_VERSION + StringSession.encode(Buffer.concat([
  67. dcBuffer,
  68. ipBuffer,
  69. portBuffer,
  70. this.authKey.key,
  71. ]))
  72. }
  73. }
  74. module.exports = StringSession